✅
WHERE用于分组前的行级过滤,作用于原始数据行,因此不能使用聚集函数(如COUNT()、SUM()、AVG()等),因为此时数据尚未分组,聚集函数无意义。✅
HAVING用于分组后的组级过滤,作用于GROUP BY产生的每个分组结果,因此可以且通常需要使用聚集函数来筛选满足条件的分组(例如:HAVING COUNT(*) > 5)。
执行顺序(逻辑顺序,非书写顺序)为:FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY
📌 示例对比:
-- ✅ 正确:WHERE 过滤单个订单,不涉及聚集SELECTcustomer_id,COUNT(*)FROMordersWHEREorder_date>='2024-01-01'-- 行级条件,合法GROUPBYcustomer_idHAVINGCOUNT(*)>3;-- 组级条件,用聚集函数,合法-- ❌ 错误:WHERE 中使用聚集函数(语法报错)-- WHERE COUNT(*) > 3 -- 不允许!应该在HAVING中写AVG(salary) > 10000,不能在WHERE中写。
✅ 正确写法:
SELECTdepartment,AVG(salary)ASavg_salaryFROMemployeesGROUPBYdepartmentHAVINGAVG(salary)>10000;❌ 错误写法(语法错误):
SELECTdepartment,AVG(salary)FROMemployeesWHEREAVG(salary)>10000-- ❌ 报错:WHERE 无法使用聚集函数GROUPBYdepartment;🔹 原因如下:
WHERE在逻辑执行顺序中位于GROUP BY之前,此时数据尚未按部门分组,每行仍是独立员工记录,AVG(salary)尚未计算(无“部门平均”这一概念),因此 SQL 引擎不允许在WHERE中使用聚集函数。HAVING在GROUP BY之后执行,此时已形成每个部门的一组数据,AVG(salary)可对每组独立计算,因此可安全用于过滤满足条件的部门组。
⚠️ 补充说明:
即使你先用子查询或 CTE 预先算出各部门平均工资,那也是将聚集结果“物化”为普通列后,才可在外层WHERE过滤——但这不改变WHERE本身不能直接调用聚集函数的本质规则。