执行顺序混乱

order of execution confusion

提问人:Kartik 提问时间:6/13/2023 最后编辑:Laurenz AlbeKartik 更新时间:6/13/2023 访问量:52

问:

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 电子邮件 花的钱
布列塔尼 莱利 [电子邮件保护] 5.83
阿诺德 天堂 [电子邮件保护] 5.14
埃莉 诺 打猎 [电子邮件保护] 5.04
史黛西 蒙哥马利 [电子邮件保护] 4.73
卡尔 密封 [电子邮件保护] 4.63

我对执行顺序感到困惑。我知道我们不能根据聚合结果进行过滤,因为尚未执行。是否发生在 或 ?AVG(Amount)WHEREAVG(Amount)GROUP BYSELECT

  1. 如果它发生在 ,则应该有三列 、 和 left。怎么还能执行?GROUP BYFirst_nameLast_nameemailAVG(Amount)HAVING SUM(AMOUNT)

  2. 如果它发生在 ,那么为什么我们仍然可以像以前一样使用 at 进行过滤?SELECTAVG(Amount)HAVINGHAVINGSELECT

SQL PostgreSQL 执行顺序

评论

1赞 nbk 6/13/2023
HAVING 在选择后执行,这就是为什么您可以使用 AVG 或 SUM 的原因

答:

1赞 tinazmu 6/13/2023 #1

在处理您的查询时,执行引擎还将评估(以及)每个first_name、last_name、电子邮件组合;因为这些分别由您的 SELECT 和 HAVING 引用。一些RDBMS不允许引用SELECT子句中尚未出现的表达式,但我想PostgreSql正在帮我们一个忙并允许它。出于您的目的,您应该假设这些聚合是在 GROUP BY 时间计算的(之后应用了 HAVE;但这实际上是一个“逻辑”顺序,因为如果引擎推断出它会更便宜并且不会改变结果,它可以更早地应用其中的一部分)。GROUP BYSUM(Amount)AVG(Amount)HAVING

评论

0赞 Kartik 6/13/2023
非常感谢。这消除了我的疑虑。
1赞 George S 6/13/2023 #2

在考虑结果时,可以认为 and 子句在子句之前进行了计算,但列定义中使用的任何聚合函数仍然可以访问基础的分解数据。GROUP BYHAVINGSELECTSELECT

考虑它的顺序是:

  1. JOINs 和子句WHERE
  2. GROUP BY;请注意,但是,您也可以在输出查询中按列分组,例如 但这是合糖GROUP BY 1, 2
  3. HAVING
  4. SELECT

您可以看到,结果列的实际计算发生在最后,因为如果将窗口函数用作访问(例如)上一行的一部分,则只能访问已包含在其中或使用聚合函数的数据,并且 or 子句删除的数据将被过滤掉。SELECTGROUP BYHAVINGWHERE