关于SQL执行顺序的疑问:AVG(Amount)的执行时机
SELECT First_name,last_name,email,ROUND (AVG(Amount),2) AS moneyspent FROM Customer INNER JOIN Payment ON Customer.customer_id= Payment.customer_id WHERE Staff_id=2 GROUP BY First_name,last_name,email HAVING SUM(Amount)>100 ORDER BY Moneyspent DESC
查询结果
| first_name | last_name | moneyspent | |
|---|---|---|---|
| Brittany | Riley | brittany.riley@sakilacustomer.org | 5.83 |
| Arnold | Havens | arnold.havens@sakilacustomer.org | 5.14 |
| Eleanor | Hunt | eleanor.hunt@sakilacustomer.org | 5.04 |
| Stacey | Montgomery | stacey.montgomery@sakilacustomer.org | 4.73 |
| Karl | Seal | karl.seal@sakilacustomer.org | 4.63 |
疑问
我对SQL的执行顺序存在疑问。我理解无法在WHERE子句中基于AVG(Amount)这类聚合结果进行过滤,因为此时聚合操作尚未执行。现请教:AVG(Amount)是在GROUP BY阶段还是SELECT阶段执行?
- 若在
GROUP BY阶段执行,此时应剩下First_name、Last_name、email和AVG(Amount)这几列,为何HAVING SUM(AMOUNT)仍能执行? - 若在
SELECT阶段执行,由于HAVING在SELECT之前执行,为何还能在HAVING中使用AVG(Amount)进行过滤?
解答
首先明确:聚合函数(如AVG、SUM)是在GROUP BY分组完成后、HAVING过滤之前统一计算的,不属于单纯的GROUP BY或SELECT阶段。
SQL的逻辑执行顺序可简化为:
FROM/JOIN:关联表获取原始数据集WHERE:过滤原始数据行(此时未分组,无法使用聚合函数)GROUP BY:按指定字段对过滤后的数据分组- 计算所有聚合值:对每个分组,一次性算出所有需要的聚合结果(不管是
SELECT还是HAVING中用到的) HAVING:用已计算好的聚合值过滤分组SELECT:选择需要的字段(分组字段+已计算的聚合值)ORDER BY:对最终结果排序
针对你的两个问题:
- 问题1:
GROUP BY仅完成分组操作,之后会计算所有涉及到的聚合函数(包括SELECT里的AVG(Amount)和HAVING里的SUM(Amount)),并非只计算SELECT中声明的聚合值,所以HAVING能正常调用SUM(Amount)进行过滤。 - 问题2:聚合函数的计算早于
HAVING的执行,当HAVING运行时,每个分组的AVG(Amount)结果已经生成,自然可以用它来过滤分组。
内容的提问来源于stack exchange,提问作者Kartik
相关产品推荐
相关产品推荐

