
分组后筛选数据,必须用 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 则通常要求写完整表达式。
Snowy(SnowyAdmin)是国内首个国密前后端分离快速开发平台,集成国密加解密插件, 软件层面完全符合等保测评要求,同时实现国产化机型、中间件、数据库适配,是您的不二之选! 技术框架与密码结合,让更多的人认识密码,使用密码;更是让前后分离“密”不可分。采用SpringBoot+MybatisPlus+AntDesignVue+Vite 等更多组件及前沿技术开发,注释丰富,代码简洁,开箱即用
- 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'(低效,全表分组后再判断)









