9、GROUP BY 对结果集的行进行分组、HAVING 子句 分组后过滤
1、GROUP BY
是 SELECT 语句的一个可选子句。GROUP BY 子句允许您根据一个或多个列的值对行进行分组。
- 按照指定列的值将表中的行分组,每个不同的行值形成一个组,相同值的行被合并到同一组中。
- 把该列中「值相同的行」全部合并成「一行」;而「值不同的行」各自成为独立的一组(也是一行)。
- 通常与聚合函数(如 COUNT()、SUM()、AVG()、MAX()、MIN() 等)一起使用,以便对每个分组执行计算。
- 与 HAVING 子句配合使用,
WHERE用于过滤分组前的行,而HAVING用于过滤分组后的结果。
语法:
SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 字段名 [ HAVING 分组后的过滤条件 ];
-- 在 SELECT 子句中的所有非聚合列(没有使用聚合函数的列)都必须出现在 GROUP BY 子句中。
例:
-- ✅ 正确 SELECT dept, COUNT(*) FROM employees GROUP BY dept; -- ❌ 错误(name 不是聚合列,没有出现在 GROUP BY 中,) SELECT dept, name, COUNT(*) FROM employees GROUP BY dept;
假设有一个订单表 orders:
| order_id | customer_id | product | amount |
|---|---|---|---|
| 1 | 101 | Laptop | 1200 |
| 2 | 102 | Mouse | 25 |
| 3 | 101 | Keyboard | 75 |
| 4 | 103 | Monitor | 300 |
| 5 | 102 | Laptop | 1100 |
执行语句:
-- 统计每位客户的订单总金额 SELECT customer_id, SUM(amount) AS total_amount FROM orders GROUP BY customer_id;
结果:
| customer_id | total_amount |
|---|---|
| 101 | 1275 |
| 102 | 1125 |
| 103 | 300 |
-- 按 product(产品)分组,统计每个产品出现了多少次(即销售次数)。
SELECT product, COUNT(*) AS sales_count
FROM orders
GROUP BY product;
结果:
| product | sales_count |
|---|---|
| Laptop | 2 |
| Mouse | 1 |
| Keyboard | 1 |
| Monitor | 1 |
核心规则
当SELECT子句的列表中包含聚合函数(如COUNT, SUM, AVG, MAX, MIN)时:
-
必须使用 GROUP BY子句,所有在SELECT中出现的非聚合列,都必须出现在GROUP BY子句中。
-
GROUP BY子句中可以包含SELECT中没有出现的非聚合列
-
SELECT中可以只包含聚合列,不包含任何非聚合列
否则,数据库无法确定“该返回哪一行的值”,结果具有不确定性,因此报错(如 MySQL Error 1140)。
2、HAVING 子句
用于对 GROUP BY 分组后的结果进行过滤。可以使用聚合函数(如 COUNT()、SUM()、AVG() 等)。
- 不能用于过滤原始行(那是
WHERE的工作)。
语法:
SELECT 列1, 聚合函数(列2) FROM 表名 GROUP BY 列1 HAVING 条件; -- 可以写聚合函数
例子
表 orders 数据:
| order_id | customer_id | product | amount |
|---|---|---|---|
| 1 | 101 | Laptop | 1200 |
| 2 | 102 | Mouse | 25 |
| 3 | 101 | Keyboard | 75 |
| 4 | 103 | Monitor | 300 |
| 5 | 102 | Laptop | 1100 |
-- 找出销售次数 ≥ 2 的产品 SELECT product, COUNT(*) AS sales_count FROM orders GROUP BY product HAVING COUNT(*) >= 2;
结果:
| product | sales_count |
|---|---|
| Laptop | 2 |
-- SQL 查询的逻辑执行顺序 FROM → WHERE → GROUP BY → 聚合计算 → HAVING → SELECT → ORDER BY → LIMIT
WHERE在分组前运行,只能访问原始列;HAVING在分组后运行,可以访问分组列 + 聚合结果。
where 和 having 的区别:
- 执行时机不同:
- where是分组之前进行过滤,不满足where条件不参与分组;
- having是分组后对结果进行过滤。
- 判断条件不同:
- where不能对聚合函数进行判断,而having可以。
本文来自博客园,作者:chao_xiong,转载请注明原文链接:https://www.cnblogs.com/chao-xiong/p/19214480

浙公网安备 33010602011771号