2012-06-12 84 views
1

我已經構建了一個接口,用戶從數據庫中獲取記錄。用戶可以選擇指定0個或更多的過濾器。有四種過濾器A,B,C,d(讓我們說的這些都是在某個表中的字段)構建動態無失敗where子句

這裏是我的查詢應該是什麼樣子:

select * from table 
where (A = v1 or B = v2 or C = v3) and D = v4 

我想拿出一個辦法來制定查詢,而當指定了特定的過濾器時,則應用該查詢,否則將被忽略。但這應該適用於所有16個案例。

我已經能夠拿出迄今這些方法是:

select * from table 
where (
    (A = v1 and 1) 
    or (B = v2 and 1) 
    or (C = v3 and 1) 
    ) 
    and D = v4 

v1或其它值設置爲-1未指定,當他們。因此,如果沒有指定它們,它們會被忽略,因爲使用另一個過濾器(來自A,B,C之間)。但是,在沒有指定A,B和C的情況下,這會失敗。在這種情況下,假使用D來結束,並且不應用D.

有沒有一種方法來與這種情況下的where子句?我也接受這個程序的解決方案,我通過代碼添加或不添加子句,但我更喜歡這種方式。我真的不想有很多if-else語句。

謝謝!

回答

1

怎麼樣使用case構建

select * 
    from table 
    where (A = CASE WHEN v1 IS NOT NULL THEN v1 else '' END) 
      OR (B = CASE WHEN v2 IS NOT NULL THEN v2 else '' END) 
      OR (C = CASE WHEN v3 IS NOT NULL THEN v3 else '' END) 
      OR (CASE WHEN v1 is null and v2 is null and v3 is null then 1 else 0 end) 
    and D = v4 
+0

+1尼斯一個,複製這個想法告訴了我答案 – Andomar

+0

所以,當A和B被指定,而C不是時,C = C給出了我的真實性,並且A或B或真實結果在A和B中沒有得到應用,所有的行都將被考慮。 –

+0

@Caffeine Yeap。同意。我更新了SQL。我假設A,B,C是varchar字段。 –

0

數據庫也很難優化動態where子句。通常情況下,他們會爲第一次調用生成最優的計劃。因此,如果您的第一次搜索是針對過濾器A和B,則查詢計劃將針對此進行優化。即使使用過濾器C和D,下一個查詢也將使用該計劃。添加代碼中的where子句往往會表現得更好。

但它是可能的,例如:

where (
      A = @FilterAValue 
      or B = @FilterBValue 
      or C = @FilterCValue 
     ) 
     and D = coalesce(@FilterDValue, D) 

然後您可以切換與FilterXValue參數的過濾器。如果A,B或C的過濾器爲null,則仍會評估or的其他部分。 A = null or B = 1unknown or B = 1相同,只有當B = 1時纔是如此。

+0

當A,B,C沒有提供時會發生什麼?如果我沒有錯,那OP是在找什麼。 –

+0

然後沒有行返回(與您的答案相同)。您可以添加'或@FilterAValue爲null,並且@FilterBValue爲null並且@FilterCValue爲null'在最後一個'或'下面返回所有行。 – Andomar

+0

最後一種情況檢查v1,v2,v3是否爲null,然後它將對所有行返回true,從而僅應用D僅濾波器。或者可能是我得到的問題是錯的:-) –

0

如果v1 - v4是你正在尋找的價值和所有的人都-1如果沒有指定,你可以這樣做:

SELECT 
    * 
FROM 
    table 
WHERE 
    (
    (A = v1 OR -1 = v1) 
    or 
    (B = v2 OR -1 = v2) 
    or 
    (C = v3 OR -1 = v3) 
) 
AND 
    (D = v4 OR -1 = v4) 
+0

假設我指定了A和B,但不是C.在這種情況下,它將是 (A = v1或B = v2或true)和D = v4,它將有點丟棄前兩個過濾器。 –