2011-12-02 45 views
21

我想在我的case語句返回多個值,如:SQL中的case語句,如何返回多個變量?

SELECT 
    CASE 
    WHEN <condition 1> THEN <value1=a1, value2=b1> 
    WHEN <condition 2> THEN <value1=a2, value2=b2> 
    ELSE <value1=a3, value3=b3> 
    END 
FROM <table> 

我當然可以的情況下病情多次寫,每次返回一個值。但是,因爲我有許多條件需要適合,所以說100。一再重複病例情況並不好。

我想問的另一個問題,如果一條記錄適合多個條件會發生什麼?這是否意味着它會返回所有這些或只是最後一個?例如條件1可能成爲條件2的一個子集。會發生什麼?

+0

這是MS SQL Server的? – MatBailie

+0

是的,這是...... – yzhang

+0

你能澄清你的情況嗎?例如,100個不同的情況條件是否會導致value1和value2中的每個值有100個不同的適用值,或者100個不同的條件中的很多是否會產生相同的結果?條件是不同領域的完全組合嗎?或者它們是單一領域的不同可能值? –

回答

13

不幸的是,基本的方法是重複自己。

SELECT 
    CASE WHEN <condition 1> THEN <a1> WHEN <condition 2> THEN <a2> ELSE <a3> END, 
    CASE WHEN <condition 1> THEN <b1> WHEN <condition 2> THEN <b2> ELSE <b3> END 
FROM 
    <table> 

幸運的是,大多數RDBMS足夠聰明,不必多次評估條件。這只是多餘的打字。


在MS SQL Server(2005+),你可以使用可能CROSS應用來替代這一點。雖然我不知道它是怎麼高性能...

SELECT 
    * 
FROM 
    <table> 
CROSS APPLY 
    (
    SELECT a1, b1 WHERE <condition 1> 
    UNION ALL 
    SELECT a2, b2 WHERE <condition 2> 
    UNION ALL 
    SELECT a3, b3 WHERE <condition 3> 
) 
    AS case_proxy 

這裏的noticable缺點是沒有ELSE當量,因爲所有的條件可以所有的返回值,他們需要的是隻有這樣陷害人們可以一次成爲真實的人。


編輯

如果呸的應答改變爲一個UNION,而不是加盟的方式,它變得非常類似於此。但是,主要區別在於它只掃描一次輸入數據集,而不是每個條件掃描一次(在您的情況下爲100次)。


編輯

我也注意到,您可以意味着由CASE語句返回的值是固定的。所有匹配相同條件的記錄在值1和值2中獲得完全相同的值。這可以形成這樣的...

WITH 
    checked_data AS 
(
    SELECT 
    CASE WHEN <condition1> THEN 1 
     WHEN <condition2> THEN 2 
     WHEN <condition3> THEN 3 
     ... 
     ELSE     100 
    END AS condition_id, 
    * 
    FROM 
    <table> 
) 
, 
    results (condition_id, value1, value2) AS 
(
    SELECT 1, a1, b1 
    UNION ALL 
    SELECT 2, a2, b2 
    UNION ALL 
    SELECT 3, a3, b3 
    UNION ALL 
    ... 
    SELECT 100, a100, b100 
) 
SELECT 
    * 
FROM 
    checked_data 
INNER JOIN 
    results 
    ON results.condition_id = checked_data.condition_id 
6

A CASE語句只能返回一個值。

你也許可以把它變成子查詢,然後JOIN它可以處理你正在處理的任何其他關係。例如(使用SQL Server 2K5 +的CTE):

WITH C1 AS (
    SELECT a1 AS value1, b1 AS value2 
    FROM table 
    WHERE condition1 
), C2 AS (
    SELECT a2 AS value1, b2 AS value2 
    FROM table 
    WHERE condition2 
), C3 AS (
    SELECT a3 AS value1, b3 AS value2 
    FROM table 
    WHERE condition3 
) 
SELECT value1, value2 
FROM -- some table, joining C1, C2, C3 CTEs to get the cased values 
; 
+0

而不是加入(可能外部聯合與coalesce語句),你可能會聯合在一起。假設對於任何給定的輸入記錄,只有一個條件是真的。即使這樣,這也會涉及掃描每個條件一次的源數據集,從而對數據進行100次掃描。 – MatBailie

+0

@Dems:是的,那也可以。 OP問題中的ELSE條件寫爲ELSE ',所以列不完全相同。我在我的答案中「固定」了,但它可能不是一個錯字。 – Yuck

+0

不錯的地方,我不會*假設*一個錯字,它可能是相關的,所以需要value2中的NULL作爲其他結果。 – MatBailie

5

CASE根據定義僅返回一個值。永遠。

它也(幾乎總是)短路,這意味着如果您的第一個條件滿足,沒有其他檢查運行。

+0

+1是否有任何條件*它不*短路? –

+0

@MarkBannister - 是的,但它們是錯誤的(在SQL Server中)。基本上我所看到的唯一情況是你在哪裏做一個變量集合的比較('CASE WHEN MAX(@var)...')。它會評估它們,但仍然返回正確的價值。 – JNK

0

您可以使用與UNION組合的子查詢。 每當你可以返回相同的字段不止一個條件使用或用括號如下例所示:

SELECT * FROM 
    (SELECT val1, val2 FROM table1 WHERE (condition1 is true) 
            OR (condition2 is true)) 
UNION 
SELECT * FROM 
    (SELECT val5, val6 FROM table7 WHERE (condition9 is true) 
            OR (condition4 is true)) 
+0

而對於其他99個條件? (這給了2個字段,但僅限於1個條件) – MatBailie

+0

使用UNION,每個條件一個子查詢。 –

+0

@Dems:你也可以在這裏使用'OR'(我編輯我的例子以適應它) –

0

在SQL CASE子句,第一個成功匹配條件應用於任何後續的匹配條件被忽略。

2

在你的情況下,你會使用兩個案例staements,你想要返回的每個值。