SQL HAVING使用误区_HAVING与WHERE对比

1次阅读

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

SQL HAVING 使用误区_HAVING 与 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 的订单数”)
text=ZqhQzanResources