嵌套连接与嵌套子查询

时间:2015-04-10 15:58:16

标签: sql sql-server performance join subquery

在此业务情景中,所有承包商每天都会为各种库存项目下订单。此数据存储在ContractorOrder表中。收到库存后,会记录这些值并将其保存在ContractorStock表中。如果订单项在ContractorOrder表中不存在,则不可能出现在ContractorStock表中。

但有时,某些物品未送达,或者交付的数量不正确,或者承包商忘记下订单。为了检查这一点,我写了这两个查询(忽略Sums相同但各个行项不同的情况 - 这只是一个简化的例子):

SELECT C.ContractorId
, C.ContractorName
, Sum(CO.Quantity) OrderQuantity
, Sum(CS.Quantity) ContractorQuantity
FROM [Contractor] C
LEFT JOIN ContractorOrder CO
  ON C.ContractorId = CO.ContractorId
  AND CO.Date = @date
LEFT JOIN
(
  ContractorStock CS
  JOIN StockCode SC
    ON CS.StockCodeId = SC.StockCodeId
    AND CS.Date = @date
)
  ON CS.ContractorId = C.ContractorId
  AND SC.StockCode = CO.StockCode
GROUP BY C.ContractorId
, C.ContractorName

http://sqlfiddle.com/#!6/55496/5

SELECT C.ContractorId
, C.ContractorName
, Sum(CO.Quantity) OrderQuantity
, Sum(CS.Quantity) ContractorQuantity
FROM [Contractor] C
LEFT JOIN ContractorOrder CO
  ON C.ContractorId = CO.ContractorId
  AND CO.Date = @date
LEFT JOIN
(
  SELECT CS.ContractorId
  , SC.StockCode
  , CS.Quantity
  FROM ContractorStock CS
  JOIN StockCode SC
    ON CS.StockCodeId = SC.StockCodeId
    AND CS.Date = @date
) CS
  ON CS.ContractorId = C.ContractorId
  AND CS.StockCode = CO.StockCode
GROUP BY C.ContractorId
, C.ContractorName

http://sqlfiddle.com/#!6/55496/2

两者都返回相同的结果,但执行计划略有不同。在这种情况下,这些查询在逻辑上是否相同?如果是,我应该更喜欢嵌套加入吗?

嵌套加入:

enter image description here

子查询:

enter image description here

1 个答案:

答案 0 :(得分:0)

你刚刚证明了什么(当涉及到不同类型的查询时)你应该让SQL Server找出最好的计划(因为SQL版本上升,引擎会越来越好,找到最好的查询计划)而你应该专注于编写产生基于设置的正确结果的SQL。

我看到的唯一区别是计算缩放器步骤接近总计划的0%,因此不值得花费大量时间来消除该步骤。

在过去(SQL Server 2000之前版本),如果你编写了连接和子查询,它实际上很重要。现在,在绝大多数情况下,将子查询更改为连接或反之亦然。

您始终希望避免逐行操作,并在可能的情况下使用seek进行替换,但是一旦您完成了此操作。