2009-06-05 39 views
2

例子:WHERE子句中的條件檢查序列是否已預定義?

SELECT * 
FROM [User] 
WHERE [Value1] > 0 
AND [Value2]/[Value1] > 3 

我想避免一個部門被零的情況。我能確定首先檢查第一個條件,如果第一個條件是錯誤的,第二個條件不會被打到?我猜想如果查詢規劃器能夠產生更多的性能,就可以重新排列順序。

+0

[Value1]/[Value1]> 3?我認爲你輸錯了,[Value1]/[Value1]幾乎總是1,除非你有0,在這種情況下,它將是未定義的。 – Joseph 2009-06-05 14:44:25

+0

當然,打錯了,修好了,謝謝。 – User 2009-06-05 14:45:27

回答

0

一般沒有。優化器找出執行查詢的最佳方式。

SQL不會產生明確的代碼:它只是對優化器的指令返回特定格式,訂單數據,過濾等

SELECT * 
FROM [User] 
WHERE [Value1] > 0 
AND [Value1]/[Value1] > 3 

--could be this 
SELECT * 
FROM 
    (SELECT * 
    FROM [User] 
    WHERE [Value1] > 0 
) foo 
WHERE [Value1]/[Value1] > 3 

--but to be safe 
SELECT * 
FROM 
    (SELECT TOP 2000000000 * 
    FROM [User] 
    WHERE [Value1] > 0 
    ORDER BY Value1 
) foo 
WHERE [Value1]/[Value1] > 3 
+0

爲什麼#2不安全? – User 2009-06-05 14:50:04

4
SELECT * 
FROM [User] 
WHERE CASE WHEN Value1 = 0 THEN 0 ELSE [Value2]/[Value1] END > 3 

,甚至更好:

SELECT * 
FROM [User] 
WHERE [Value2]/NULLIF([Value1], 0) > 3 

除以NULL總是安全的。

注意不是如果你有很多的[Value1] = 0在你的表和[Value1]索引,那麼下面的查詢:

SELECT * 
FROM [User] 
WHERE [Value1] > 0 
     AND [Value2]/NULLIF([Value1], 0) > 3 

,將使用索引,只是跳過錯誤的價值觀。

但是,不應該依賴這個,並且仍然應該使用NULLIF。無論如何,它幾乎都是免費的。

0

你最初的SQL代碼將很好地工作:)

0

那麼對於初學者...

Value1/Value1 == 1 //always... 

但假設其不同的列。

SELECT top 20 * from [User] 
WHERE 
CASE WHEN Value2 > 0 
    THEN convert(decimal(18,2), Value1)/convert(decimal(18,2), Value2) 
    ELSE 0 
END > 3 
0

您不能指望按所列順序處理您的條件的服務器。一般而言,優化程序將按照它認爲是更快的順序運行它們。通常情況下,你列出的應該是安全的,但我已經看到優化器感到困惑的邊緣情況。使優化的事情[Value1] > 0條件會更快

一個很好的辦法就是對Value1Value2的索引。