2018年3月8日 星期四

利用CASE WHEN條件式及OR邏輯運算子合併查詢邏輯

一些查詢需求中,當輸入特定查詢條件時,則依此條件進行篩選;若無任何查詢條件,則傳回所有資料。常見作法會將此查詢SQL獨立撰寫,再以UNION ALL(切記勿用UNION,但建議自行測試)指令將兩段查詢語法組合。語法如下,煩請自行測執行。
--建立測試資料
SELECT * INTO #Store
FROM (VALUES ('DDR', 50,  '光華店')
           , ('DDR2', 10,  '公館店')
           , ('DDR4', 80,  '站前店')
           , ('DDR2', 10,  '公館店')          
     ) Store (Prod, Qty, Loc)

-----------
DECLARE @Prod varchar(10)            --測試1未輸入資料

--DECLARE @Prod varchar(10) = 'DDR2' --測試2輸入資料

--1. 未輸入Prod
SELECT Prod, Qty, Loc
FROM #Store
WHERE 1=1
     AND @Prod IS NULL
UNION ALL --使用UNION將僅剩3筆(DDR2少1筆) 
--2. 輸入Prod
SELECT Prod, Qty, Loc
FROM #Store
WHERE 1=1
     AND Prod =@Prod

前述兩段不同條件以聯集運算合併之SQL,將利用CASE WHEN條件式及OR邏輯運算子即可合併。其中,條件式(1)採用CASE WHEN條件式判斷查詢條件是否已輸入,以OR邏輯運算子結合條件式(2)查詢產品之條件,SQL及結果如下:

SQL
Result
測試1
未輸入
--測試1: 未輸入資料
DECLARE @Prod varchar(10)

SELECT *
FROM #Store
WHERE 1= CASE WHEN @Prod IS NULL THEN 1 END --(1)成立
      OR Prod = @Prod                       --(2)不成立
測試2
輸入
--測試2: 輸入資料
DECLARE @Prod varchar(10) = 'DDR4'

SELECT *
FROM #Store
WHERE 1= CASE WHEN @Prod IS NULL THEN 1 END --(1)不成立
      OR Prod = @Prod                       --(2)成立
測試1(未輸入)中,運算式(1)結果為1=1即成立,條件式(2)則不成立,因任何資料不等於NULL 包含NULL本身,由於兩運算式是使用OR邏輯運算子結合,雖不成立但可忽略,將傳回所有資料(4);測試2(輸入)中,運算式(1)1=NULL即不成立,條件式(2)則具有完全決定權,將回傳1DDR4之產品。


4 則留言:

  1. 有多個欄位篩選,我會簡潔的寫法:
    SELECT Prod, Qty, Loc
    FROM #Store
    WHERE
    ((@Prod IS NULL) OR (Prod = @Prod))
    AND
    ((@Loc IS NULL) OR (Loc = @Loc))

    回覆刪除
    回覆
    1. 的確是簡潔的寫法。用CASE WHEN串成1=1對我比較容易判讀,當轉成1=1即代表全部,供參。

      刪除
  2. SELECT *
    FROM #Store
    WHERE Prod = isnull(@Prod,Prod)

    回覆刪除