HAVING 用于分组后筛选,WHERE 用于分组前过滤;HAVING 必须配合 GROUP BY 使用,可引用聚合函数,WHERE 不能;误用会导致错误或性能下降。

HAVING 是 SQL 中用于对分组后的结果进行筛选的关键字,但它常被误用——很多人把它当成 WHERE 的替代品,或在没用 GROUP BY 时强行使用。核心区别在于:WHERE 在分组前过滤行,HAVING 在分组后过滤组。
WHERE 和 HAVING 的执行顺序不同
SQL 查询的逻辑执行顺序决定了它们的作用时机:
- FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
- WHERE 在 GROUP BY 之前运行,只能引用原始表中的列,不能用聚合函数(如 COUNT()、SUM())
- HAVING 在 GROUP BY 之后运行,可以引用分组字段和聚合函数
常见误用:在没有 GROUP BY 时写 HAVING
以下写法是错误的(多数数据库会报错):
SELECT name FROM users HAVING COUNT(*) > 1;
因为没分组,COUNT(*) 没有意义,HAVING 无组可筛。想查重复姓名,应先 GROUP BY name,再 HAVING:
SELECT name FROM users GROUP BY name HAVING COUNT(*) > 1;
混淆 WHERE 和 HAVING 导致结果偏差
例如:查“每个部门中薪资高于 5000 的员工数,且该部门总人数超过 3 人”
- 错误写法(把条件全塞 HAVING):
SELECT dept, COUNT(*) FROM emp GROUP BY dept HAVING salary > 5000 AND COUNT(*) > 3;
→ salary 是单行字段,不在 GROUP BY 中,也不能在 HAVING 中直接比较(除非是聚合值) - 正确写法:
SELECT dept, COUNT(*) FROM emp WHERE salary > 5000 GROUP BY dept HAVING COUNT(*) > 3;
→ 先用 WHERE 筛出高薪员工,再按部门分组,最后用 HAVING 筛部门数量
能用 WHERE 就别用 HAVING,性能更优
WHERE 过滤发生在聚合前,减少参与分组的数据量;HAVING 是对已聚合的结果再过滤,数据量更大,开销更高。
- 要查“订单金额大于 100 的客户订单数”,优先 WHERE:
SELECT customer_id, COUNT(*) FROM orders WHERE amount > 100 GROUP BY customer_id; - 若写成 HAVING:
SELECT customer_id, COUNT(*) FROM orders GROUP BY customer_id HAVING MAX(amount) > 100;
→ 会先为所有客户分组统计,再过滤,效率低,语义也不等价(这里是查“客户最高订单>100”,不是“订单>100 的订单数”)






























