目录

MySQL GROUP BY

在MySQL中,GROUPBY子句用于将结果集根据指定的字段或者表达式进行分组。有时候,我们需要将结果集按照某个维度进行汇总。这在统计数据的时候经常用到,考虑以下的场景:按班级求取平均成绩。按学生汇总某个人的总分。按年或者月份统计销售额。按国家或者地区统计用户数量。这些正是GROUPBY子句发挥作用

在 MySQL 中, GROUP BY 子句用于将结果集根据指定的字段或者表达式进行分组。

有时候,我们需要将结果集按照某个维度进行汇总。这在统计数据的时候经常用到,考虑以下的场景:

  • 按班级求取平均成绩。
  • 按学生汇总某个人的总分。
  • 按年或者月份统计销售额。
  • 按国家或者地区统计用户数量。

这些正是 GROUP BY 子句发挥作用的地方。

GROUP BY 语法

GROUP BY 子句是 SELECT 语句的可选子句。 GROUP BY 子句语法如下:

SELECT column1[, column2, ...], aggregate_function(ci)
FROM table
[WHERE clause]
GROUP BY column1[, column2, ...];
[HAVING clause]

说明:

  • column1[, column2, ...] 是分组依据的字段,至少一个字段,可以多个字段。
  • aggregate_function(ci) 是聚合函数。这是可选的,但是一般都用得到。
  • SELECT 后的字段必须是分组字段中的字段。
  • WHERE 子句是可选的,用来过滤结果集中的数据。
  • HAVING 子句是可选的,用来过滤分组数据。

经常使用的聚合函数主要有:

  • SUM(): 求总和
  • AVG(): 求平均值
  • MAX(): 求最大值
  • MIN(): 求最小值
  • COUNT(): 计数

GROUP BY 实例

在以下实例中,我们使用 Sakila 示例数据库中的 actor 表和 payment 表。

简单的 GROUP BY 实例

我们使用 GROUP BY 子句查看 actor 表中的姓氏列表。

SELECT last_name
FROM actor
GROUP BY last_name;
+--------------+
| last_name    |
+--------------+
| AKROYD       |
| ALLEN        |
| ASTAIRE      |
| BACALL       |
| BAILEY       |
...
| ZELLWEGER    |
+--------------+
121 rows in set (0.00 sec)

本例中,使用 GROUP BY 子句按照 last_name 字段对数据进行分组。

本例的输出结果与以下使用 DISTINCT 的 SQL 输出结果完全一样:

SELECT DISTINCT last_name FROM actor;

GROUP BY 与聚合函数实例

我们使用 GROUP BY 子句和聚合函数 COUNT() 查看 actor 表中的姓氏列表以及每个姓氏的次数。

SELECT last_name, COUNT(*)
FROM actor
GROUP BY last_name
ORDER BY COUNT(*) DESC;
+--------------+----------+
| last_name    | COUNT(*) |
+--------------+----------+
| KILMER       |        5 |
| NOLTE        |        4 |
| TEMPLE       |        4 |
| AKROYD       |        3 |
| ALLEN        |        3 |
| BERRY        |        3 |
...
| WRAY         |        1 |
+--------------+----------+
121 rows in set (0.00 sec)

本例中,执行的顺序如下:

  1. 首先使用 GROUP BY 子句按照 last_name 字段对数据进行分组。
  2. 然后使用聚合函数 COUNT(*) 汇总每个姓氏的行数。
  3. 最后使用 ORDER BY 子句按照 COUNT(*) 降序排列。

这样,数量最多的姓氏排在最前面。

GROUP BY, LIMIT, 聚合函数实例

以下实例使用 GROUP BY 子句,LIMIT 子句和聚合函数 SUM() 返回总消费金额排名前 10 位的客户。

SELECT customer_id, SUM(amount) total
FROM payment
GROUP BY customer_id
ORDER BY total DESC
LIMIT 10;
+-------------+--------+
| customer_id | total  |
+-------------+--------+
|         526 | 221.55 |
|         148 | 216.54 |
|         144 | 195.58 |
|         137 | 194.61 |
|         178 | 194.61 |
|         459 | 186.62 |
|         469 | 177.60 |
|         468 | 175.61 |
|         236 | 175.58 |
|         181 | 174.66 |
+-------------+--------+
10 rows in set (0.02 sec)

本例中,执行的顺序如下:

  1. 首先使用 GROUP BY 子句按照 customer_id 字段对数据进行分组。
  2. 然后使用聚合函数 SUM(amount) 汇总每个客户的 amount 字段,并使用 total 作为别名。
  3. 然后使用 ORDER BY 子句按照 total 降序排列。
  4. 最后使用 LIMIT 10 子句返回前 10 个记录行。

GROUP BY 和 HAVING 实例

以下实例使用 GROUP BY 子句,HAVING 子句和聚合函数 SUM() 返回总消费金额在 180 以上的客户。

SELECT customer_id, SUM(amount) total
FROM payment
GROUP BY customer_id
HAVING total > 180
ORDER BY total DESC;
+-------------+--------+
| customer_id | total  |
+-------------+--------+
|         526 | 221.55 |
|         148 | 216.54 |
|         144 | 195.58 |
|         137 | 194.61 |
|         178 | 194.61 |
|         459 | 186.62 |
+-------------+--------+
6 rows in set (0.02 sec)

本例中,执行的顺序如下:

  1. 首先使用 GROUP BY 子句按照 customer_id 字段对数据进行分组。
  2. 然后使用聚合函数 SUM(amount) 汇总每个客户的 amount 字段,并使用 total 作为别名。
  3. 然后使用 HAVING 过滤结果集中 total 大于 180 的数据行。
  4. 最后使用 ORDER BY 子句按照 total 降序排列。

HAVING 子句用来过滤 GROUP BY 分组的数据,需要使用逻辑表达式作为条件,其中逻辑表达式中的字段或表达式只能使用分组使用的字段和聚合函数。

结论

在本文中,我们介绍了在 MySQL 中使用 GROUP BY 子句将结果集根据指定的列或者表达式进行分组。以下是 GROUP BY 子句的要点:

  • GROUP BY 子句用于将结果集根据指定的字段或者表达式进行分组。
  • GROUP BY 子句的分组字段或表达式至少一个,可以多个。
  • HAVING 子句是可选的,用来过滤分组数据。
  • GROUP BY 子句经常用于数据统计汇总,通常使用聚合函数。