
分组后筛选数据,必须用 HAVING,不能用 WHERE —— 因为 WHERE 在分组前执行,而 HAVING 作用于分组结果(即聚合后的数据)。
HAVING 必须跟在 GROUP BY 后面
语法顺序不能错:select → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT。如果没写 GROUP BY,单独用 HAVING 会报错(除非数据库支持扩展语法,如 mysql 5.7 以前允许,但不推荐)。
- ✅ 正确:
GROUP BY dept_id HAVING count(*) > 1 - ❌ 错误:
HAVING COUNT(*) > 1(无 GROUP BY) - ⚠️ 注意:WHERE 中不能出现聚合函数,如
WHERE COUNT(*) > 1是非法的
HAVING 可以使用 SELECT 中的别名(部分数据库支持)
MySQL、postgresql 等支持在 HAVING 中直接引用列别名;SQL Server 和 oracle 则通常要求写完整表达式。
- MySQL 写法(可读性好):
SELECT dept_id, COUNT(*) AS cnt FROM emp GROUP BY dept_id HAVING cnt > 5 - 兼容写法(通用):
HAVING COUNT(*) > 5或HAVING COUNT(emp_id) > 5
组合多个条件时,优先用 HAVING 过滤聚合结果
当需要同时满足“人数大于 3”且“平均薪资高于 8000”时,WHERE 无法完成,必须 HAVING:
GROUP BY dept_id HAVING COUNT(*) > 3 AND AVG(salary) >= 8000- 注意:AVG(salary) 是每组计算出的值,WHERE 拿不到这个结果
- 若还想排除 NULL 薪资,可在聚合函数中加条件:
AVG(CASE WHEN salary IS NOT NULL THEN salary END),再在 HAVING 中判断
性能提示:先用 WHERE 减少数据量,再 GROUP BY + HAVING
HAVING 是对分组结果筛选,不减少中间计算量。想提升效率,应尽量把能提前过滤的条件放在 WHERE:
- 比如查“2023 年入职且部门人数超 5 人”的部门:
WHERE hire_date >= '2023-01-01' GROUP BY dept_id HAVING COUNT(*) > 5 - 避免写成:
GROUP BY dept_id HAVING COUNT(*) > 5 AND MAX(hire_date) >= '2023-01-01'(低效,全表分组后再判断)