2013-04-16 93 views
2

我想優化where子句。它會反覆運行,並且我試圖讓查詢更快完成,但是這個或許會顯着降低查詢速度。如果你們能幫助,那將會很棒!Where子句優化

WHERE 
((Date1 >= @startdate 
    AND Date1 <= @enddate 
    AND @RunBy = 0) 
OR (date2 BETWEEN @startdate AND @enddate 
    AND @RunBy = 1 
    AND date2 BETWEEN @startdate AND @enddate) 
OR (date3 BETWEEN @startdate AND @enddate 
    AND @RunBy = 2) 
OR (date4 >= @startdate 
    AND date4 <= @enddate 
    AND @RunBy = 3)) 

我試圖把案件或如果,但它只是沒有爲我工作。

+2

什麼是你的數據庫?您是否嘗試使用查詢計劃器? –

+3

你怎麼知道'OR'是減慢速度的那個?你檢查查詢執行計劃嗎? – MarcinJuraszek

+1

第二個條件有兩個重複的陳述 - 是否應該這是你想要的? –

回答

4

你的where子句可以被改寫爲:

WHERE CASE @RunBy 
    WHEN 0 THEN Date1 
    WHEN 1 THEN Date2 
    WHEN 2 THEN Date3 
    WHEN 3 THEN Date4 
END BETWEEN @startdate AND @enddate 

這應該加快速度,因爲你最小化正在執行的比較次數。

它也更容易閱讀和理解,這是好的編程的本質,它也看起來很酷!

+0

謝謝,這正是我正在尋找的。 –

+0

沒問題。當你達到15的聲望時,不要爲了回來而投票回答:) – Bohemian

+0

很酷,我會盡快趕到:) –

0

比較查詢的性能,你 「變」 成手術室UNION承滴盤,例如: 而不是

WHERE (A = @A) 
OR (B = @B) 

嘗試

SELECT ... 
FROM ... 
WHERE [email protected] 

UNION ALL 

SELECT ... 
FROM ... 
WHERE [email protected] 

值得一試。

+0

有時效果不錯。我有'UNIONs'就像因爲阻塞形式的並行性而導致問題。另一種解決方案是創建一個臨時表並使用* n *個連續的'insert/select'語句填充它。優化器足夠聰明,可以基於局部變量對恆定值的測試來短路執行。 –

0

我看到date2中有一個條件的重複部分。

OR (date2 BETWEEN @startdate AND @enddate 
AND @RunBy = 1 AND date2 BETWEEN @startdate AND @enddate) 

而且你能堅持到語法的一個 - 要麼BETWEEN或> =和< =組合使用。不要以爲它會導致性能差異。

1

如果您期望不同的執行計劃,則必須使用不同的查詢文本。如果date1,date2,date3和date4上有索引,它們將不會與當前的「多面」查詢一起使用。根據您希望使用的執行計劃分解爲4個查詢。

IF @RunBy = 0 
BEGIN 
    SELECT... 
    FROM ... 
    WHERE date1 ... 
END 
ELSE IF @RunBy = 1 
BEGIN 
    SELECT ... 
    FROM ... 
    WHERE date2 ... 
END 
ELSE IF... 
+0

+1:但是你應該注意,如果將@ RunBy傳遞給存儲過程或參數化查詢,緩存的執行計劃將在第一次調用時根據「@ RunBy」的值創建。這不能導致問題。爲了消除這個問題,需要首先聲明一個局部變量,並將其設置爲傳入參數的值。呃......用查詢優化器搞砸了大家的歡樂。 –

0

是這樣的嗎?

where case @RunBy 
     when 1 then Date1 
     when 2 then Date2 
     when 3 then Date3 
     when 4 then Date4 
     else  null 
     end between @startDate and @endDate 

這並不一定會提高你的查詢計劃,因爲我不相信優化器將能夠使用您Date1-4列的任何指標,因爲case是一個函數:指數不能被應用到函數表達式。