HAVING必须紧跟GROUP BY之后,仅用于筛选分组后的结果,支持聚合函数和分组字段作为条件,不能替代WHERE过滤单行数据,且必须与GROUP BY共存,否则报错。

HAVING 必须跟在 GROUP BY 后面,且只能用聚合函数或分组字段做条件;写错位置或混用 WHERE 逻辑,查不到数据是常态。
HAVING 必须和 GROUP BY 一起出现
单独写 HAVING 会报错,MySQL 不允许它脱离分组上下文。你不能把它当 WHERE 的替代品来过滤单行数据。
-
HAVING的存在前提是已有分组结果,所以GROUP BY是硬性前置条件 - 如果只想要筛选原始行,用
WHERE;想筛“哪个组满足条件”,才轮到HAVING - 错误示例:
SELECT name, COUNT(*) FROM users HAVING COUNT(*) > 1;→ 报错ERROR 1140: Mixing of GROUP columns...
WHERE 和 HAVING 混用时的执行顺序很关键
MySQL 实际执行顺序是:FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT。这个顺序决定了你能用什么、不能用什么。
-
WHERE阶段看不到聚合结果,所以WHERE COUNT(*) > 5是语法错误 -
HAVING阶段已经完成分组和聚合,HAVING AVG(price) 是合法的 - 先用
WHERE缩小数据集(比如加时间范围),再GROUP BY,最后HAVING筛组,性能更优 - 示例:
SELECT customer_id, SUM(amount) FROM orders WHERE created_at >= '2026-01-01' GROUP BY customer_id HAVING SUM(amount) > 5000;
HAVING 条件里能用哪些东西?
只允许两类表达式:聚合函数(COUNT、SUM、AVG、MAX、MIN、GROUP_CONCAT)或出现在 GROUP BY 子句里的字段。
- 允许:
HAVING COUNT(*) >= 3、HAVING MAX(score) > 90、HAVING department = 'sales'(前提是department在GROUP BY中) - 不允许:
HAVING salary > 8000(salary未聚合也未分组)、HAVING name LIKE '%a%'(同理) - 别名不能直接用于
HAVING条件(MySQL 5.7+ 支持,但 8.0 默认关闭;稳妥起见,重复写聚合表达式) - 错误写法:
SELECT dept, AVG(salary) AS avg_sal FROM staff GROUP BY dept HAVING avg_sal > 6000;→ 建议改成HAVING AVG(salary) > 6000
容易被忽略的性能陷阱
HAVING 是在分组完成后才执行的,意味着 MySQL 必须先把所有分组算出来,再逐个判断是否保留。数据量大时,这一步开销不小。
- 如果业务上能用
WHERE提前过滤(比如限定某几个部门),就别全量分组再筛 - 确保
GROUP BY字段有索引,否则分组本身就很慢 -
HAVING COUNT(*) > 1查重复值时,不如用EXISTS或窗口函数(MySQL 8.0+)更高效 - 避免在
HAVING里写复杂子查询或函数调用,它们会在每个分组上重复执行
真正麻烦的不是语法记不住,而是把 HAVING 当成“高级 WHERE”去用——它不处理行,只处理组。一旦混淆这个边界,查出来的结果要么为空,要么错得离谱。


















