where不能用聚合函数,因执行时未分组且无聚合值;必须用having配合group by筛选聚合结果,且having只能引用group by字段或聚合函数。

WHERE 不能用 COUNT、SUM 等聚合函数
这是最常踩的坑:一写 COUNT(*) > 5 就报错,提示“invalid use of aggregate function”。因为 WHERE 执行时,数据还没分组,更没算出聚合值——它只认原始表里的字段。
比如想查“员工数超 5 的部门”,下面这句一定失败:
SELECT dept_id FROM employee WHERE COUNT(*) > 5 GROUP BY dept_id;
正确做法是把条件挪到 HAVING 里。记住:只要条件里出现 COUNT、SUM、AVG、MAX、MIN,就必须用 HAVING,且必须配 GROUP BY。
HAVING 必须跟 GROUP BY 搭配(绝大多数情况)
单独写 HAVING SUM(amount) > 1000 在标准 SQL 中不合法,会报错或行为不可靠(如 SQLite 允许但结果错)。数据库需要明确“按什么分组后才去算这个 SUM”。
常见误用场景:
- 想筛“总订单额超 1 万的客户” → 必须
GROUP BY customer_id,再HAVING SUM(amount) > 10000 - 想筛“单笔订单超 1 万” → 直接用
WHERE amount > 10000,不需要GROUP BY或HAVING - 漏写
GROUP BY却写了HAVING→ 大多数数据库(PostgreSQL、MySQL 8.0+、SQL Server)直接报错
WHERE 过滤越早越好,性能差别明显
假设一张表有 100 万行,其中只有 1 万行属于“2025 年订单”。如果用 HAVING 筛“2025 年订单总额 > 5000”,数据库得先把全部 100 万行分组、聚合,再过滤;而用 WHERE order_date >= '2025-01-01',先干掉 99 万行,剩下 1 万行再分组,快得多。
手动 Telegram 斜杠命令,用于查看 Codex 状态及使用情况。用户发送 /codex_usage、/codex_usage default、/codex_usage all 等时触发。
所以:
- 能用
WHERE过滤的条件,别塞进HAVING(比如status = 'paid'、region IN ('华东', '华南')) -
HAVING只保留真正依赖聚合结果的逻辑,例如HAVING COUNT(*) > 10、HAVING AVG(score) >= 85 - 组合使用很常见:
WHERE先缩小数据集,GROUP BY分组,HAVING再筛组
HAVING 能用的字段非常有限
HAVING 后面只能写两类东西:
- 出现在
GROUP BY子句里的字段(如GROUP BY dept_id, year,则HAVING dept_id = 1合法) - 聚合函数(如
COUNT(*)、SUM(salary))
下面这句会报错:
SELECT dept_id, AVG(salary) FROM employee GROUP BY dept_id HAVING salary > 5000;
因为分组后,salary 已不存在——每组只剩一个 AVG(salary) 值。想筛“平均工资超 5000 的部门”,得写 HAVING AVG(salary) > 5000。
容易被忽略的是:有些数据库(如旧版 MySQL)允许这种写法但结果不一致,切勿依赖。










