case when的判断顺序_CASE 表达式
一、語法及作用
使用CASE表達式可以幫助我們解決復雜的查詢問題,相當于條件判斷的函數,判斷每一行是不是滿足條件。
CASE WHEN (判斷表達式) THEN (表達式)WHEN (判斷表達式) THEN (表達式)WHEN (判斷表達式) THEN (表達式)....ELSE(表達式) END;CASE 表達式會從對最初的WHEN子句中的“< 求值表達式 >”進行求值開始執行。所謂求值,就是要調查該表達式的真值是什么。如果結果為真(TRUE),那么就返回THEN子句中的表達式,CASE表達式的執行到此為止。如果結果不為真,那么就跳轉到下一條WHEN子句的求值之中。 如果直到最后的WHEN子句為止返回結果都不為真,那么就會返回ELSE中的表達式,執行終止。
二、注意事項
- 在發現為真的 WHEN 子句時, CASE 表達式的真假值判斷就會中止,而剩余的 WHEN 子句會被忽略。因此,為了避免引起不必要的混亂,使用 WHEN 子句時要注意條件的排他性。
- CASE 表達式里各個分支返回的數據類型必須一致,如果不一致,則需使用CAST()函數轉換數據類型。
- 雖然CASE表達式中的ELSE子句可以省略,但為了讓SQL語句更加容易理解,還是盡量不要省略。
- CASE 表達式中的 END 不能省略。
- 使用CASE表達式能夠將SELECT語句的結果進行組合。
三、適用情況
3.1 將已有編號方式轉換為新的方式并統計
例如,統計下表 PopTbl 中的內容,得出如右表“統計結果”所示的結果。
首先,可以通過定義一個包含“地區編號”列的視圖來實現。但是這種方法需要添加的行的數量將等同于統計對象的編號個數,而且很難動態地修改。因此,可以使用CASE表達式來實現:
SELECT CASE WHEN pref_name IN ('德島', '香川', '愛媛', '高知') THEN '四國'WHEN pref_name IN ('福岡', '佐賀', '長崎') THEN '九州'ELSE '其他'END AS district,SUM(population) AS population FROM PopTbl GROUP BY CASE WHEN pref_name IN ('德島', '香川', '愛媛', '高知') THEN '四國'WHEN pref_name IN ('福岡', '佐賀', '長崎') THEN '九州'ELSE '其他'END ORDER BY population DESC;這里的關鍵在于將SELECT子句里的CASE表達式復制到 GROUP BY 子句里。后期修改時有可能只改了一處而忘了另一處。因此,可以在 GROUP BY 子句中引用 SELECT 子句中定義的別名 (如下代碼所示),這樣寫出來的 SQL 語句確實非常簡潔,而且可讀性也很好 。
SELECT CASE WHEN pref_name IN ('德島', '香川', '愛媛', '高知') THEN '四國'WHEN pref_name IN ('福岡', '佐賀', '長崎') THEN '九州'ELSE '其他'END AS district,SUM(population) AS population FROM PopTbl GROUP BY district ORDER BY population DESC;嚴格來說,這種寫法是違反標準 SQL 的規則的,因為 GROUP BY 子句比 SELECT 語句先執行。事實上,在 Oracle、DB2、 SQL Server 等數據庫里采用這種寫法時就會出錯。 不過在 PostgreSQL 和 MySQL 中,這個查詢語句就可以順利執行。這是因為,這些數據庫在執行查詢語句時,會先對 SELECT 子句里的列表進行掃描,并對列進行計算。不過因為這是違反標準的寫法,所以這里不強烈推薦大家使用。
3.2 行列轉換:在聚合函數中使用CASE WHEN 表達式
3.2.1 統計下表 PopTbl2 中的內容,得出如右表“統計結果”所示的結果。
SELECT pref_name,SUM(CASE WHEN sex = 1 THEN population ELSE 0 END) AS '男性人口',SUM(CASE WHEN sex = 0 THEN population ELSE 0 END) AS '女性人口' FROM PopTbl2 GROUP BY pref_name;3.2.2 統計 PopTbl2 表中的容,得出如下表所示的結果。
SELECT CASE WHEN sex = 1 THEN 'male' ELSE 'female' END AS sex2, SUM(population) AS 'total', SUM(CASE WHEN pref_name = '德島' THEN population ELSE 0 END) AS '德島', SUM(CASE WHEN pref_name = '香川' THEN population ELSE 0 END) AS '香川', SUM(CASE WHEN pref_name = '愛媛' THEN population ELSE 0 END) AS '愛媛', SUM(CASE WHEN pref_name = '高知' THEN population ELSE 0 END) AS '高知', SUM(CASE WHEN pref_name IN ('德島', '香川', '愛媛', '高知') THEN population ELSE 0 END) AS '四國' FROM PopTbl2 GROUP BY sex2;3.3 表之間的數據匹配:在 CASE WHEN 表達式中使用子查詢
方法一:子查詢 (X 和 O 表示)
SELECT course_name,CASE WHEN course_id IN (SELECT course_id FROM OpenCourses WHERE month = '200706')THEN 'O' ELSE 'X' END AS 'June',CASE WHEN course_id IN (SELECT course_id FROM OpenCourses WHERE month = '200707')THEN 'O' ELSE 'X' END AS 'July',CASE WHEN course_id IN (SELECT course_id FROM OpenCourses WHERE month = '200708')THEN 'O' ELSE 'X' END AS 'August' FROM CourseMaster;方法二:聯結 (0 和 1表示)
SELECT a.course_name,MAX(CASE WHEN b.month = '200706' THEN 1 ELSE 0 END) AS 'June',MAX(CASE WHEN b.month = '200707' THEN 1 ELSE 0 END) AS 'July',MAX(CASE WHEN b.month = '200708' THEN 1 ELSE 0 END) AS 'August' FROM CourseMaster AS a LEFT JOIN OpenCourses AS b ON a.course_id = b.course_id GROUP BY a.course_name;3.4 在 CASE 表達式中使用聚合函數
如表 StudentClub 所示,這張表的主鍵是“學號、社團 ID”,存儲了學生和社團之間多對多的關系。有的學生同時加入了多個社團(如學號為 100、200 的學生),有的學生只加入了某一個社團(如學號為 300、400、500 的學生)。對于加入了多個社團的學生,我們通過將其“主社團標志”列設置為 Y 或者 N 來表明哪一個社團是他的主社團;對于只加入了一個社團的學生,我們將其“主社團標志”列設置為 N。
接下來,我們需要查詢獲取只加入了一個社團的學生的社團 ID 以及獲取加入了多個社團的學生的主社團 ID,并將結果存放在一個表中。
方法一:UNION ALL
SELECT std_id, MAX(club_id) AS 'main_club' FROM StudentClub GROUP BY std_id HAVING COUNT(club_id) = 1 UNION ALL SELECT std_id, club_id AS 'main_club' FROM StudentClub WHERE main_club_flg = 'Y' ORDER BY std_id;方法二:CASE WHEN 表達式
SELECT std_id, CASE WHEN COUNT(club_id) = 1 THEN MAX(club_id)ELSE MAX(CASE WHEN main_club_flg = 'Y' THEN club_id ELSE NULL END) END AS 'main_club' FROM StudentClub GROUP BY std_id;3.5 多列數據的最大值
針對每一個key_col,取出x、y、z中最大的值 (取出每一行的最大值)
方法一:自己想的
SELECT key_col,CASE WHEN x > y AND x > z THEN xWHEN y > x AND y > z THEN yELSE zEND AS 'max_col' FROM Greatests;方法二:窮盡討論
SELECT key_col,CASE WHEN CASE WHEN x < y THEN x ELSE y END < z THEN z ELSECASE WHEN x < y THEN y ELSE x ENDEND AS greatest FROM Greatests;方法三:運用 UNION ALL 進行行列轉換
SELECT key_col, MAX(col) AS greatest FROM(SELECT key_col, x AS col FROM GreatestsUNION ALLSELECT key_col, y AS col FROM GreatestsUNION ALLSELECT key_col, z AS col FROM Greatests) AS a GROUP BY key_col;方法四:GREATEST() 函數
SELECT key_col, GREATEST(x, y, z) AS greatest FROM Greatests;GREATEST() 函數介紹:
https://www.w3schools.com/sql/func_mysql_greatest.asp?www.w3schools.com3.6 在 ORDER BY 語句中使用 CASE WHEN 表達式
3.6.1 針對3.5中的結果,將結果按照 B-A-D-C的順序排序
SELECT key_col,CASE WHEN CASE WHEN x < y THEN x ELSE y END < z THEN z ELSECASE WHEN x < y THEN y ELSE x ENDEND AS greatest FROM Greatests ORDER BY (CASE WHEN key_col = 'B' THEN 1WHEN key_col = 'A' THEN 2WHEN key_col = 'D' THEN 3ELSE 4 END);3.6.2 如果job是"SALESMAN",則根據"comm"排序,否則根據"sal"排序
方法1:
SELECT ename, sal, job, comm FROM emp ORDER BY CASE WHEN job = 'SALESMAN' THEN commELSE salEND;方法2:
SELECT ename, sal, job, comm,CASE WHEN job = 'SALESMAN' THEN commELSE salEND AS ordered FROM emp ORDER BY 5;3.7 使用 CASE WHEN 語句在 UPDATE 語句里進行條件分支:
例如:對公司工資表中(Salaries)的員工工資(salary)進行更新:對當前工資為 30 萬日元以上的員工,降薪 10%;對當前工資為 25 萬日元以上且不滿 28 萬日元的員工,加薪 20%。
UPDATE SalariesSET salary = CASE WHEN salary > 300000 THEN salary * 0.9WHEN salary >250000 AND salary <280000 THEN salary * 1.2ELSE salaryEND;3.8 調換主鍵值:
通常,當我們想調換主鍵值 a 和 b 時,需要將主鍵值臨時轉換成某個中間值。使用這種方法時需要執行 3 次 UPDATE 操作:
-- 1. 將 a 轉換為中間值 d UPDATE SomeTable SET p_key = 'd' WHERE p_key = 'a';-- 2.將b調換為a UPDATE SomeTable SET p_key = 'a' WHERE p_key = 'b';-- 3.將d調換為b UPDATE SomeTable SET p_key = 'b' WHERE p_key = 'd';但是,如果使用 CASE 表達式,1 次就可以做到:
UPDATE SomeTable SET p_key = CASE WHEN p_key = 'a' THEN 'b'WHEN p_key = 'b' THEN 'a'ELSE p_keyEND;一般來說需要進行這樣的調換大多是因為表的設計出現了問題,所以請先重新審視一下表的設計,去掉不必要的約束。
四、練習
表關系請參考如下文章 (SQL面試50題) 中的四張表
shanshant:SQL面試50題?zhuanlan.zhihu.com練習一:查詢每門課程的及格人數和不及格人數
方法一:自己寫的
SELECT c_id, SUM(及格) AS 及格人數, SUM(不及格) AS 不及格人數 FROM (SELECT c_id,CASE WHEN score >=60 THEN 1 ELSE 0 END AS '及格',CASE WHEN score <60 THEN 1 ELSE 0 END AS '不及格'FROM scores) AS c GROUP BY c_id;方法二:參考猴子老師的
SELECT c_id, SUM(CASE WHEN score >= 60 THEN 1ELSE 0END) AS 及格人數, SUM(CASE WHEN score < 60 THEN 1ELSE 0END) AS 不及格人數 FROM scores GROUP BY c_id;練習二:使用分段 [100-85], [85-70], [70-60], [<60]來統計各科成績,分別統計:各分數段人數,課程號和課程名稱。
SELECT a.c_id, b.c_name, SUM(CASE WHEN score >= 85 THEN 1ELSE 0END) AS 85至100分數段, SUM(CASE WHEN score >= 70 AND score < 85 THEN 1ELSE 0END) AS 70至85分數段, SUM(CASE WHEN score >= 60 AND score < 70 THEN 1ELSE 0END) AS 60至70分數段, SUM(CASE WHEN score < 60 THEN 1ELSE 0END) AS 不及格 FROM scores AS a RIGHT JOIN classes AS b ON a.c_id = b.id GROUP BY a.c_id, b.c_name;總結
以上是生活随笔為你收集整理的case when的判断顺序_CASE 表达式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 看本地网速_安装 ANSYS 本地帮助
- 下一篇: matlab调用python函数未定义函