SQL中WHERE与HAVING配合GROUP BY使用的相关问题咨询
SELECT Employees.LastName, COUNT(Orders.OrderID) AS NumberOfOrders FROM Orders INNER JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID WHERE LastName = 'Davolio' OR LastName = 'Fuller' GROUP BY LastName HAVING COUNT(Orders.OrderID) > 25;
问题1:上述SQL语句可正常执行的原因
核心原因是WHERE和GROUP BY、HAVING的执行阶段和作用对象完全不冲突,符合SQL标准语法规则:
标准SQL的核心执行顺序如下:
- 先执行FROM和JOIN逻辑,关联订单表和员工表得到全量关联数据集
- 再执行WHERE子句,过滤掉LastName不是Davolio、Fuller的行,仅保留目标员工的关联数据
- 之后执行GROUP BY,按LastName对过滤后的数据分组
- 再计算每组的COUNT聚合值
- 最后执行HAVING子句,过滤掉聚合后订单数不大于25的分组
你之前接触到的「GROUP BY应当搭配HAVING而非WHERE」是错误认知,二者作用场景完全不同,并非互斥关系。
问题2:WHERE和HAVING配合GROUP BY的适用场景
当你需要同时满足两类过滤需求时,就可以使用这种组合写法:
- 第一类是针对非聚合字段的过滤:过滤条件可以直接基于原始行数据判断,不需要等待分组聚合计算完成,这类条件放到WHERE中,还可以提前减少需要分组处理的数据量,大幅提升查询性能
- 第二类是针对聚合结果的过滤:过滤条件依赖分组后的聚合计算结果(比如计数、求和、平均值等的判断),这类条件必须放到HAVING中
比如要统计「北京、上海两个城市的门店中,季度销售额超过100万的门店」,就可以先通过WHERE过滤掉其他城市的门店数据,再按门店分组计算销售额,最后通过HAVING过滤掉销售额不足100万的分组,属于非常典型的组合使用场景。
注意:WHERE中不允许使用聚合函数作为判断条件,因为执行WHERE的时候分组和聚合计算还未执行,无法拿到聚合结果,这类条件必须放到HAVING中。
内容的提问来源于stack exchange,提问作者ruedi
相关产品推荐
相关产品推荐

