SQL Where 子句顺序
Posted
技术标签:
【中文标题】SQL Where 子句顺序【英文标题】:SQL Where clause order 【发布时间】:2022-01-20 06:33:45 【问题描述】:我有这个 SQL 查询:
SELECT
Runs.runID, Runs.runDateTime,
COUNT(Files.destFileID) AS FileCount
FROM
Runs
LEFT OUTER JOIN
Files ON Files.runID = Runs.runID
WHERE
FileCount > 0
GROUP BY
Runs.runID, Runs.runDateTime
ORDER BY
Runs.runDateTime
它运行良好并在没有WHERE
行的情况下显示预期结果,但我确实需要过滤结果数据,因为这意味着。
我得到的错误是
列名“FileCount”无效
在WHERE
关键字之后。
我一直在阅读,但在网上找不到任何包含我拥有的所有元素的资源。
【问题讨论】:
这是最高结果from a Google search SQL 语句不会从上到下解释。顺序是 FROM、WHERE、GROUP、HAVING、SELECT、ORDER(没有穷举,例如窗口函数在 where 和 group 之间完成)。您不能在序列的早期部分中使用序列后期的某些内容 (HAVING 是应用于 GROUP BY 的 WHERE) 【参考方案1】:您不能通过 WHERE
中的别名引用列,您需要在 WHERE
中重复表达式。然而,由于你的表达式是一个聚合,你实际上需要把它放在HAVING
:
SELECT R.runID,
R.runDateTime,
COUNT(F.destFileID) AS FileCount
FROM dbo.Runs R
LEFT OUTER JOIN dbo.Files ON F.runID = R.runID
GROUP BY R.runID,
R.runDateTime
HAVING COUNT(F.destFileID) > 0
ORDER BY R.runDateTime;
详细说明为什么您不能在 WHERE
(或此处为 HAVING
)中通过别名引用该列,这是由于 Logical Processing Order of the SELECT statement,这表明 WHERE
已处理第 4 部分,和HAVING
7th,但是,SELECT
是第8个处理部分。由于在处理WHERE
时尚未处理SELECT
,因此无法引用其中定义的内容[SELECT
]。在编程意义上,这就像在定义变量之前尝试引用它。
根据文档,操作顺序如下(请注意并非总是如此,但之前链接的文档对此进行了更详细的介绍):
来自 开启 加入 在哪里 分组依据 使用多维数据集或使用汇总 有 选择 不同 订购人 顶部
【讨论】:
是的,那些文档坏了。它缺少APPLY
、OFFSET
和窗口函数,而ON
和JOIN
是同一件事(除非它指的是嵌套连接,它也缺少),
@Charlieface 您可以随时提出问题或为文档发送 PR;它们是开源的。在这里说他们“坏了”并没有任何意义。【参考方案2】:
谢谢拉努,我会在 10 分钟后接受你的回答,但是在发布我的问题后,我发现我可以对整个事情进行子查询:
SELECT *
FROM (
SELECT Runs.runID ,Runs.runDateTime ,COUNT(Files.destFileID) AS FileCount
FROM Runs
LEFT OUTER JOIN Files ON Files.runID = Runs.runID
WHERE FileCount > 0
GROUP BY Runs.runID, Runs.runDateTime
ORDER BY Runs.runDateTime
)
AS results
WHERE FileCount > 0
ORDER BY runDateTime
这也有效。有谁知道这些选项中的哪些是最佳做法,或者每个选项的性能?
【讨论】:
这似乎是一个新问题,基于最后你问哪个是更好的做法或执行者。尽管您可以检查查询计划并查看它们的运行方式是否不同(我怀疑不是)。 我本来是想给出答案的,但是 larnu 的答案在 Sql 方面是更快更有效的方式。影响会在更大的数据时显示出来。 这个性能(和查询计划)将完全相同,虽然我注意到你不能在派生表中有ORDER BY
(你也不需要它)
我会使用 HAVING,因为它更整洁以上是关于SQL Where 子句顺序的主要内容,如果未能解决你的问题,请参考以下文章
在SQL语句中同时包含where子句,groupby子句,having子句及聚集函数,将按照怎么样的顺序执行?