我使用Microsoft SQL Server,但我想这个问题适用于所有SQL语言。 如果我有:
SELECT OrderHeaderID
,isNull(Qty,0) AS Qty
FROM OrderHeader
LEFT JOIN (
SELECT OrderHeaderID
,Sum(Qty) AS Qty
FROM OrderDetail
GROUP BY OrderHeaderID
) OrderDetail
ON OrderDetail.OrderHeaderID = OrderHeader.OrderHeaderID
WHERE Criteria = 'X'
然后,在应用条件之前,是否会对所有OrderDetail行执行GROUP BY?换句话说,我应该注意将标准应用于GROUP BY以及外部SELECT吗?
顺便说一句,如果你看到这行代码有任何改进,那么请评论。答案 0 :(得分:3)
关于第一个问题,很难说出编译查询时优化程序发现了什么。我认为你的内部聚合首先被执行。
关于你的第二个问题,这两个选择可能更容易理解
SELECT OrderHeader.OrderHeaderID
,isNull(Sum(OrderDetail.Qty),0) AS Qty
FROM OrderHeader
LEFT JOIN OrderDetail
ON OrderDetail.OrderHeaderID = OrderHeader.OrderHeaderID
WHERE OrderHeader.Criteria = 'X'
GROUP BY OrderHeader.OrderHeaderID
或
select OrderHeaderId,
IsNull(
(Select sum(qty) from OrderDetails d
where d.OrderHeaderId = OrderHeader.OrderHeaderId)
,0) as qty
from OrderHeader
where Criteria='X'
答案 1 :(得分:1)
数据库可以自由执行查询,但只要它返回正确的结果就可以。这就是为什么SQL被称为声明性语言:你指定你想要的东西,而不是你想要的东西。
但是,在这种情况下,如果您将Criteria = 'X'
移至left join
,则查询会改变含义。然后查询将包含没有任何OrderDetails的OrderHeaders。所以数据库不能自由地进行你建议的重构。
答案 2 :(得分:1)
答案是“是” - 将左连接表的非关键条件移动到ON
子句将提高性能,因为行将尽早从结果中消除,而不是离开在进行所有连接之后过滤它的where子句,尤其是在对其他表进行进一步连接时。