HAVING用于分组后筛选聚合结果,必须配合GROUP BY使用;WHERE在分组前过滤原始行且不能用聚合函数,而HAVING可基于COUNT()、AVG()等结果过滤组。

HAVING 用于对 GROUP BY 分组后的结果进行条件筛选,它作用于分组聚合后的数据,而不是原始行记录。这和 WHERE 的关键区别在于:WHERE 在分组前过滤行,HAVING 在分组后过滤组。
为什么不能用 WHERE 筛选分组结果?
WHERE 子句执行时,数据尚未分组,也无法访问聚合函数(如 COUNT()、SUM()、AVG())的结果。比如你想查“订单数超过 5 的客户”,COUNT(*) 还没算出来,WHERE 就没法判断。
HAVING 的基本写法
必须配合 GROUP BY 使用,通常放在 GROUP BY 之后、ORDER BY 之前:
SELECT 列名, 聚合函数
FROM 表名
GROUP BY 分组列
HAVING 条件表达式
例如,查每个部门中平均工资高于 8000 的部门:
SELECT dept_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY dept_id
HAVING AVG(salary) > 8000;
HAVING 常见使用场景
- 筛选满足聚合值条件的组,如 “订单总数 ≥ 10 的用户”、“商品销量总和 > 1000 的品类”
- 结合多个聚合函数,如 HAVING COUNT(*) > 1 AND AVG(price)
- 引用 SELECT 中的别名(MySQL 支持,但标准 SQL 不推荐依赖此特性):SELECT dept_id, COUNT(*) AS cnt FROM emp GROUP BY dept_id HAVING cnt >= 5
- 可与 WHERE 共存:WHERE 先过滤原始数据,再分组,最后 HAVING 筛组。例如:“只统计2023年入职且平均薪资超9000的部门”
注意事项
- HAVING 后的字段,要么是 GROUP BY 中的列,要么是聚合函数结果
- 不要在 HAVING 中写未聚合的普通列(除非它也在 GROUP BY 中)
- 性能上,优先用 WHERE 减少分组前的数据量;HAVING 是最后一步,无法利用索引加速(除非优化器能下推)
- 如果不需要分组,只是按条件过滤,就用 WHERE,别误用 HAVING










