2012-05-25 24 views
3

我要完成從case when如何在SQL Server的CASE中使用「IN」?

If @chk='Y' 
    Select * From Table1 Where [email protected] 
Else If (@chk='N') 
    Select * From Table1 Where Column1 In (Select column2 from Table2) 

下面我想這可能是這樣的:

Select * 
From Table1 
Where 
    Case When @chk='Y' Then 
     [email protected] 
    Else 
     Column1 In (Select column2 from Table2) 
End 

我知道還有比Case When其他替代解決方案。但是有可能使用Case when來做到這一點嗎?

+0

他們是兩個不同的表,是否正確? – mattytommo

+0

Table1和Table2是不同的表。 – Vivek

回答

6

的情況是返回一個值的表達式。它不用於控制流量。

WHERE (Column1 = @Value AND @chk = 'Y') 
OR (@chk <> 'Y' AND Column1 IN (SELECT column2 FROM table2)); 
4

CASE用於表達式的內聯評估。這不是真的動態WHERE子句。

對於你所要求的解決方案是使用一個WHERE條款用括號分組:

Select * From Table1 
Where 
(@chk='Y' AND [email protected]) 
OR 
(@chk <> 'Y' AND Column1 In (Select column2 from Table2)) 
+1

+1打8秒,但沒有得到接受。 –

+0

@AaronBertrand我猜太多了! ;) – JNK

+1

而且我甚至有一個錯字... –

0

可以使用案例陳述中WHERE子句。他們的方式你會這樣做:

Select * 
From Table1 
Where (Case When @chk='Y' and [email protected] the 'Y' 
      Else Column1 In (Select column2 from Table2) 
     End) = 'Y' 

通常,你不想這樣做,主要是出於美學原因。也就是說,在某些情況下,使用案例編寫的代碼比使用其中的相應邏輯更具可讀性。事實上,這可能就是這種情況。

不過,更重要的是,出於性能原因或語法,您想要短路的情況。使用WHERE子句幾乎可以保證子查詢的評估。它有可能不會使用CASE來執行。

錯誤是另一種情況。當列不是數字,下面可以生成SQL類型的錯誤,因爲SQL不保證條款的順序在WHERE:

where isnumeric(val) = 1 and cast(val to float) < 100.0 

在另一方面,下面的工作:

where (case when isnumeric(val) = 1 then cast(val to float) end) < 100.0 

個人而言,當面臨這種情況時,我更願意將這種情況置於子查詢中,因此WHERE將包含一個列名。

1

我們也可以用CASE WHEN來做,它可能是理想的。我回答一個類似的問題(Three conditions on one column of table)對這個問題

Select * From Table1 
Where 
    CASE @Chk 
    WHEN 'Y' THEN 
     CASE WHEN [email protected] THEN 1 END 
    WHEN 'N' THEN 
     CASE WHEN Column1 In (Select column2 from Table2) THEN 1 END 
    END = 1 

CASE可以稍微力短路表達。在點

案例爲什麼OR應避免:http://www.sqlfiddle.com/#!6/29531/2

鑑於這兩個功能相同的查詢:

-- using CASE WHEN to convince your RDBMS to short-circuit things: 
select count(*) 
from usermessages um 
join "user" u  
on 
(case when um.friendId = 1 then um.sourceUserId else um.friendId end) = u.userId; 


-- pure boolean approach, RDBMS can't short-circuit the OR expression 
select count(*) 
from usermessages um 
join "user" u  
on 
(um.friendId = 1 and um.sourceUserId = u.userId) 
or 
(um.friendId = u.userId); 

鑑於從http://www.sqlfiddle.com/#!6/29531/2樣本數據,第一個查詢只用了88毫秒,而第二查詢耗時4.7秒。速度的差異是用戶非常感覺的。

這不是一條硬性規則,你仍然必須檢查你的RDBMS如何實際執行你的查詢。在使用CASE WHEN時,您的RDBMS可能仍不會執行您的出價(短路)。最好的規則仍然是分析您的查詢