Sql-Server

左外連接 - 查詢計劃中的排序操作 - 調整這個簡單查詢的任何方法?

  • February 20, 2017

在處理以下查詢以回答此問題時:

如何以與數據庫無關的方式查詢圖表數據?

具有以下表格:

CREATE TABLE [dbo].[#foo] ( 
[creation]  DATETIME                         NOT NULL,
[value]     MONEY                                NULL,
[DT]        AS (CONVERT([date],[CREATION])) PERSISTED)


-- add a clustered index on the dt column
CREATE CLUSTERED INDEX CI_FOO ON #FOO(DT)
GO

和另一個加入表格:

create table #bar (dt date primary key clustered)
go

可以在此處找到將數據載入到這些表中的資訊

但是在執行以下查詢時:

WITH RADHE AS (
SELECT THE_ROW=ROW_NUMBER() OVER(PARTITION BY B.DT ORDER BY B.DT),
      THE_DATE=B.dt,
      THE_NUMBER_OF_RECORDS_ON_THIS_DAY=CASE WHEN F.DT IS NULL THEN 0 ELSE COUNT(*) OVER (PARTITION BY F.DT ) END ,
      THE_TOTAL_VALUE_FOR_THE_DAY=COALESCE(SUM(F.VALUE) OVER (PARTITION BY b.DT ),0)

FROM #BAR B
LEFT OUTER JOIN #FOO F
ON B.dt = F.dt
)

--get rid of the duplicates and present the result
SELECT 
THE_DATE,
THE_NUMBER_OF_RECORDS_ON_THIS_DAY,
THE_TOTAL_VALUE_FOR_THE_DAY
FROM RADHE
WHERE THE_ROW = 1

我在下面得到類似這張圖片的東西,這正是我想要的。

在此處輸入圖像描述

但是生成的執行計劃有幾個排序和嵌套循環操作,如下圖所示。

完整的查詢計劃可以在這裡找到。

在此處輸入圖像描述

這是一個非常簡單的操作,兩個表之間的左外連接,索引已經排序,因此我想知道是否可以簡化查詢計劃。

或者,我可以更改查詢程式碼。

為什麼我們在查詢計劃中需要nested loops2 次和2 次?sort

您有一個提供排序的索引,B.DT

  • THE_ROW該計劃首先使用此順序進行評估
  • 然後右手排序順序F.DT進行評估THE_NUMBER_OF_RECORDS_ON_THIS_DAY
  • 最後,左手排序使事情恢復B.DT正常THE_TOTAL_VALUE_FOR_THE_DAY

您可以通過簡單地更改 CTE 中列的順序來擺脫其中一種排序,以便F.DT最後出現的列(此不必要排序的連接項在此處

WITH RADHE AS (
SELECT THE_ROW=ROW_NUMBER() OVER(PARTITION BY B.DT ORDER BY B.DT),
      THE_DATE=B.dt ,
      THE_TOTAL_VALUE_FOR_THE_DAY=COALESCE(SUM(F.VALUE) OVER (PARTITION BY b.DT ),0),
      THE_NUMBER_OF_RECORDS_ON_THIS_DAY=CASE WHEN F.DT IS NULL THEN 0 ELSE COUNT(*) OVER (PARTITION BY F.DT ) END

FROM #BAR B
LEFT OUTER JOIN #FOO F
ON B.dt = F.dt
)

THE_NUMBER_OF_RECORDS_ON_THIS_DAY但是您可以通過更改 to 的定義來擺脫兩者

CASE WHEN F.DT IS NULL THEN 0 ELSE COUNT(*) OVER (PARTITION BY B.DT ) END

因此它使用與其餘功能相同的分區定義。

這不應該改變您的範例中的任何內容,因為您的CASE表達式0無論如何都會分配給任何不匹配的行。

至於計劃的其餘部分,請參閱分區和公共子表達式假離線

(事後計劃沒有排序)

在此處輸入圖像描述

引用自:https://dba.stackexchange.com/questions/164922