SQL中的HAVING子句是数据查询中常用的筛选工具,它主要配合GROUP BY子句使用,用来对分组后的结果集进行条件过滤,和WHERE子句的作用场景有明显区别。

HAVING子句基本语法
HAVING子句通常跟在GROUP BY子句之后,基本语法结构如下:
SELECT 列名1, 聚合函数(列名2) FROM 表名 GROUP BY 列名1 HAVING 筛选条件;
这里的筛选条件通常是聚合函数的结果,或者分组列的相关判断,不能直接使用未在GROUP BY中出现的非聚合列作为条件,这一点和WHERE子句不同。
HAVING和WHERE的核心区别
很多用户会混淆HAVING和WHERE的用法,两者的核心差异如下:
- WHERE子句在分组之前执行,用来筛选原始数据行,不能使用聚合函数作为条件
- HAVING子句在分组之后执行,用来筛选分组后的结果,可以使用聚合函数作为条件
- 如果查询中没有GROUP BY子句,HAVING的行为和WHERE类似,但依然不建议混用
常见使用实例
实例1:筛选订单数量超过3的用户
假设有一张订单表orders,包含user_id和order_id字段,我们需要查询下单数量超过3的用户ID和下单总数:
SELECT user_id, COUNT(order_id) AS order_count FROM orders GROUP BY user_id HAVING COUNT(order_id) > 3;
实例2:筛选平均薪资高于8000的部门
假设有一张员工表employees,包含dept_id、salary字段,查询平均薪资高于8000的部门ID和平均薪资:
SELECT dept_id, AVG(salary) AS avg_salary FROM employees GROUP BY dept_id HAVING AVG(salary) > 8000;
实例3:结合WHERE和HAVING使用
如果需要先筛选入职时间在2023年之后的员工,再统计各部门的平均薪资,只保留平均薪资高于7000的部门:
SELECT dept_id, AVG(salary) AS avg_salary FROM employees WHERE hire_date >= '2023-01-01' GROUP BY dept_id HAVING AVG(salary) > 7000;
这个例子中WHERE先过滤了入职时间符合条件的员工,再进行分组和HAVING筛选,符合两者的执行顺序逻辑。
使用注意事项
- HAVING子句中使用的列必须是SELECT中出现的分组列或者聚合函数结果,否则会报错
- 如果需要对分组结果排序,可以在HAVING之后添加ORDER BY子句,排序规则不影响HAVING的筛选逻辑
- 不同数据库对HAVING的支持略有差异,比如MySQL允许HAVING使用SELECT中定义的别名,而部分数据库不支持,实际使用时需要结合对应数据库的规范调整