HAVING必须跟在GROUP BY之后,因其作用对象是分组后的聚合结果而非原始行;WHERE过滤行,HAVING过滤组,二者执行阶段不同、不可互换,且HAVING中可使用聚合函数而WHERE不可。

HAVING 必须跟在 GROUP BY 后面用
单独写 HAVING 会报错,比如 SELECT user_id, COUNT(*) FROM logs HAVING COUNT(*) > 10 —— 这条语句在 MySQL、PostgreSQL、SQL Server 全部不合法。SQL 执行顺序是 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY,HAVING 的作用对象是分组后的临时结果集,没分组就没有“组内聚合值”可筛。
正确写法必须显式加 GROUP BY:
SELECT user_id, COUNT(*) AS cnt FROM logs GROUP BY user_id HAVING COUNT(*) > 10
- 如果漏掉
GROUP BY user_id,数据库直接拒绝执行 -
GROUP BY列不必全出现在SELECT中,但SELECT中所有非聚合字段都必须在GROUP BY中出现(严格模式下) - MySQL 5.7+ 默认开启
sql_mode=ONLY_FULL_GROUP_BY,违反这点会报错;旧版可能只警告,结果不可靠
HAVING 和 WHERE 不能混用同一个聚合函数
WHERE 在分组前过滤行,不能用聚合函数;HAVING 在分组后过滤组,必须用聚合函数。常见错误是把本该放 HAVING 的条件写进 WHERE:
-- ❌ 错误:COUNT(*) 在 WHERE 中无效 SELECT dept, AVG(salary) FROM emp WHERE COUNT(*) > 5 GROUP BY dept <p>-- ✅ 正确:移到 HAVING SELECT dept, AVG(salary) FROM emp GROUP BY dept HAVING COUNT(*) > 5
-
WHERE salary > 5000可以,因为salary是原始列;WHERE AVG(salary) > 5000不可以 - 想先筛高薪员工再统计部门均薪?用
WHERE筛行:WHERE salary > 5000,再GROUP BY+HAVING筛组 - 性能上,
WHERE越早过滤数据量越小,HAVING是最后一步,代价更高
ORDER BY 中能用 HAVING 里的别名,但 WHERE 不行
很多用户卡在别名使用上。聚合字段的别名(如 COUNT(*) AS cnt)在 HAVING 和 ORDER BY 中可以直接用,但在 WHERE 中完全不可见:
SELECT user_id, COUNT(*) AS cnt FROM logs GROUP BY user_id HAVING cnt > 10 ORDER BY cnt DESC
-
HAVING cnt > 10合法,等价于HAVING COUNT(*) > 10 -
ORDER BY cnt DESC合法,SQL 标准允许在ORDER BY中引用SELECT列别名 -
WHERE cnt > 10语法错误——cnt此时还不存在 - 注意:某些老版本 SQLite 或特定方言可能不支持
HAVING中用别名,稳妥起见优先写原表达式
NULL 值会让 HAVING 条件意外失效
聚合函数遇到全 NULL 组时行为容易被忽略:COUNT(*) 返回 0,但 COUNT(col)、AVG(col)、SUM(col) 遇到全 NULL 会返回 NULL,而 HAVING NULL > 5 结果为 UNKNOWN,该组被直接剔除(不是保留,也不是报错):
SELECT category, AVG(price) AS avg_price FROM products GROUP BY category HAVING AVG(price) > 100
- 如果某
category下所有price都是NULL,AVG(price)返回NULL,整行不会出现在结果中 - 想保留这类组?得用
COALESCE(AVG(price), 0) > 100或显式判断:HAVING AVG(price) > 100 OR AVG(price) IS NULL -
COUNT(*)不受 NULL 影响,但COUNT(col)会跳过 NULL 值——这是唯一一个“计数但忽略 NULL”的聚合函数
聚合筛选真正麻烦的不是语法,而是搞清哪一步数据还在、哪一步已经塌缩成组。HAVING 看似简单,但和 NULL、别名作用域、执行顺序搅在一起时,很容易查半天发现只是少了个 GROUP BY 或写错了括号位置。

















