最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何在SQL中使用GROUP BY和HAVING过滤分组后的数据?
时间:2026-06-18 09:10:52 编辑:袖梨 来源:一聚教程网
GROUP BY 和 HAVING 必须配合使用才能过滤分组结果;单独 HAVING 会报错,因无分组则无“分组后”数据可筛;SELECT 非聚合字段必须出现在 GROUP BY 中,否则触发 ERROR 1055;HAVING 只能引用聚合函数或分组字段,不可用原始行单值字段。
GROUP BY 和 HAVING 必须一起用才能过滤分组后的结果;单独写 HAVING 会报错,因为没有分组就没有“分组后”的数据可筛。
GROUP BY 后 SELECT 字段必须合法
MySQL(及多数标准 SQL)要求:SELECT 列表里的每个非聚合字段,都得出现在 GROUP BY 子句中。否则直接报错 ERROR 1055(在严格模式下)。
- ✅ 正确:
SELECT department, COUNT(*) FROM employees GROUP BY department; - ❌ 错误:
SELECT name, department, COUNT(*) FROM employees GROUP BY department;——name既没在GROUP BY里,也没套聚合函数,数据库不知道该取哪一行的name。 - ⚠️ 注意:MySQL 5.7+ 默认启用
ONLY_FULL_GROUP_BY模式,这个限制是硬性的;关掉它只是掩盖问题,不是解决问题。
HAVING 只能用聚合结果或分组字段做条件
HAVING 是对「每组聚合完之后」那行结果做判断,所以条件里可以放心用 COUNT(*)、SUM(amount) 这类,但不能用原始行的单值字段(除非它也在 GROUP BY 里)。
- ✅ 正确:
HAVING COUNT(*) > 3、HAVING AVG(salary) >= 12000、HAVING department = 'tech'(因为department是分组字段) - ❌ 错误:
HAVING salary > 10000——salary不是分组字段,也不是聚合结果,这行根本不存在于 HAVING 执行时的上下文中。 - ? 小技巧:如果想先筛高薪员工再分组,应该用
WHERE salary > 10000放在 GROUP BY 前面,而不是硬塞进 HAVING。
WHERE 和 HAVING 的执行顺序不能颠倒
SQL 实际执行顺序是:FROM → WHERE → GROUP BY → 聚合计算 → HAVING → SELECT → ORDER BY。这个顺序决定了什么能做什么不能做。
- WHERE 在分组前运行,所以它快——能提前减少参与分组的数据量,尤其对大表很关键。
- HAVING 在分组后运行,是对已经算好的组进行筛选,无法跳过聚合计算。比如
HAVING COUNT(*) > 100,数据库必须先把所有组的计数全算出来,再一个个比。 - ? 场景对比:查“订单总额超 5000 且下单次数 ≥ 3 的客户”。
→ 先WHERE order_date >= '2025-01-01'缩小范围;
→ 再GROUP BY customer_id;
→ 最后HAVING SUM(amount) > 5000 AND COUNT(*) >= 3。
最容易被忽略的是:HAVING 条件里写的别名(比如 AS total),在某些数据库(如 PostgreSQL)里可以直接用,但在 MySQL 8.0 之前不支持——得重复写 SUM(amount) > 5000,不能写 total > 5000。别名可用性取决于具体版本和 SQL 模式,别默认它一定行。