首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL CASE 語句完整指南:語法、應用場景與常見陷阱

     編輯:關於SqlServer

SQL CASE 表達式的兩種基本語法

SQL 中的 CASE 表達式是實現條件邏輯的核心工具,分為「簡單 CASE」與「搜尋 CASE」兩種形式,兩者功能等價,但適用場景略有不同。

1. 簡單 CASE 函數

適合單一欄位與多個固定值的比對:

CASE sex
    WHEN '1' THEN '男'
    WHEN '2' THEN '女'
    ELSE '其他'
END

2. 搜尋 CASE 函數

支援複雜條件判斷(如範圍、複合條件),彈性更高:

CASE 
    WHEN sex = '1' THEN '男'
    WHEN sex = '2' THEN '女'
    ELSE '其他'
END

關鍵差異:簡單 CASE 僅能做等值比較,搜尋 CASE 可使用任意布林表達式(含 IN、BETWEEN、LIKE、IS NULL 等)。

核心行為:首次匹配即返回

CASE 表達式會依序評估 WHEN 條件,首個符合條件的分支即刻返回,後續分支自動忽略。此特性常被誤用,導致邏輯錯誤:

-- 錯誤示範:永遠無法得到「第二類」
CASE 
    WHEN col_1 IN ('a', 'b') THEN '第一類'
    WHEN col_1 IN ('a')     THEN '第二類'  -- 永遠不會被執行
    ELSE '其他'
END

正確做法是將更嚴格的條件前置,或改用互斥條件。

六大經典應用場景

場景一:動態分組統計(避免建立 View)

需求:依國家歸屬洲際,統計人口總數。

SELECT 
    SUM(population),
    CASE country
        WHEN '中國' THEN '亞洲'
        WHEN '印度' THEN '亞洲'
        WHEN '日本' THEN '亞洲'
        WHEN '美國' THEN '北美洲'
        WHEN '加拿大' THEN '北美洲'
        WHEN '墨西哥' THEN '北美洲'
        ELSE '其他'
    END AS continent
FROM Table_A
GROUP BY 
    CASE country
        WHEN '中國' THEN '亞洲'
        WHEN '印度' THEN '亞洲'
        WHEN '日本' THEN '亞洲'
        WHEN '美國' THEN '北美洲'
        WHEN '加拿大' THEN '北美洲'
        WHEN '墨西哥' THEN '北美洲'
        ELSE '其他'
    END;

同樣邏輯可用於薪資分級統計:

SELECT
    CASE 
        WHEN salary <= 500 THEN '1'
        WHEN salary > 500 AND salary <= 600 THEN '2'
        WHEN salary > 600 AND salary <= 800 THEN '3'
        WHEN salary > 800 AND salary <= 1000 THEN '4'
        ELSE NULL
    END AS salary_class,
    COUNT(*)
FROM Table_A
GROUP BY
    CASE 
        WHEN salary <= 500 THEN '1'
        WHEN salary > 500 AND salary <= 600 THEN '2'
        WHEN salary > 600 AND salary <= 800 THEN '3'
        WHEN salary > 800 AND salary <= 1000 THEN '4'
        ELSE NULL
    END;

場景二:單一查詢實現多條件橫向分組

需求:一張表同時輸出各國男、女性口數(避免 UNION 多次掃表)。

SELECT 
    country,
    SUM(CASE WHEN sex = '1' THEN population ELSE 0 END) AS male_pop,
    SUM(CASE WHEN sex = '2' THEN population ELSE 0 END) AS female_pop
FROM Table_A
GROUP BY country;

此技巧將縱向資料轉為橫向報表,極大簡化查詢邏輯。

場景三:CHECK 約束中的條件驗證

需求:女員工薪資必須 > 1000,男員工不限。

-- 使用 CASE 的正確寫法
CONSTRAINT check_salary CHECK (
    CASE 
        WHEN sex = '2' THEN 
            CASE WHEN salary > 1000 THEN 1 ELSE 0 END
        ELSE 1
    END = 1
)

-- 僅用 CHECK 會導致男員工無法插入
CONSTRAINT check_salary CHECK (sex = '2' AND salary > 1000)  -- 錯誤

場景四:條件式 UPDATE 避免多次掃表

需求:薪資 ≥ 5000 減 10%,2000–4600 增 15%,其餘不變。若分兩條 UPDATE,中間值會被二次修改。

UPDATE Personnel
SET salary = CASE 
    WHEN salary >= 5000 THEN salary * 0.9
    WHEN salary >= 2000 AND salary < 4600 THEN salary * 1.15
    ELSE salary  -- 必須保留,否則不符合條件的行會變 NULL
END;

進階應用:交換主鍵值(無需臨時表):

UPDATE SomeTable
SET p_key = CASE 
    WHEN p_key = 'a' THEN 'b'
    WHEN p_key = 'b' THEN 'a'
    ELSE p_key
END
WHERE p_key IN ('a', 'b');

場景五:跨表資料一致性比對

利用 IN 或 EXISTS 子查詢,標記匹配狀態:

-- 使用 IN
SELECT keyCol,
    CASE WHEN keyCol IN (SELECT keyCol FROM tbl_B) 
         THEN 'Matched' ELSE 'Unmatched' END AS Label
FROM tbl_A;

-- 使用 EXISTS(通常效能較佳)
SELECT keyCol,
    CASE WHEN EXISTS (
        SELECT * FROM tbl_B WHERE tbl_A.keyCol = tbl_B.keyCol
    ) THEN 'Matched' ELSE 'Unmatched' END AS Label
FROM tbl_A;

場景六:聚合函數內嵌 CASE 實現複雜邏輯

需求:單門課學生回傳該課程 ID,多門課學生回傳主修課程 ID。

SELECT std_id,
    CASE 
        WHEN COUNT(*) = 1 THEN MAX(class_id)
        ELSE MAX(CASE WHEN main_class_flg = 'Y' THEN class_id ELSE NULL END)
    END AS main_class
FROM Studentclass
GROUP BY std_id;

此處巧妙結合 COUNT、MAX 與巢狀 CASE,單一查詢解決雙重邏輯。

新手常犯錯誤:NULL 比較陷阱

CASE col_1
    WHEN 1     THEN 'Right'
    WHEN NULL  THEN 'Wrong'  -- 永遠不會執行!
END

WHEN NULL 等同於 WHEN col_1 = NULL,結果永遠為 UNKNOWN。正確寫法:

CASE 
    WHEN col_1 = 1     THEN 'Right'
    WHEN col_1 IS NULL THEN 'Wrong'
END

總結

CASE 表達式是 SQL 中最靈活的條件邏輯工具,掌握其順序評估、NULL 語義與聚合函數結合技巧,能將複雜業務邏輯封裝在單一聲明式查詢中,提升可維護性與效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved