網(wǎng)站首頁 編程語言 正文
CASE 表達式分為簡單表達式與搜索表達式,其中搜索表達式可以覆蓋簡單表達式的全部能力,我也建議只寫搜索表達式,而不要寫簡單表達式。
簡單表達式:
SELECT CASE city WHEN '北京' THEN 1 WHEN '天津' THEN 2 ELSE 0 END AS abc FROM test
搜索表達式:
SELECT CASE WHEN city = '北京' THEN 1 WHEN city = '天津' THEN 2 ELSE 0 END AS abc FROM test
明顯可以看出,簡單表達式只是搜索表達式 a = b
的特例,因為無法書寫任何符號,只要條件換成 a > b
就無法勝任了,而搜索表達式不但可以輕松勝任,甚至可以寫聚合函數(shù)。
CASE 表達式里的聚合函數(shù)
為什么 CASE 表達式里可以寫聚合函數(shù)?
因為本身表達式就支持聚合函數(shù),比如下面的語法,我們不會覺得奇怪:
SELECT sum(pv), avg(uv) from test
本身 SQL 就支持多種不同的聚合方式同時計算,所以將其用在 CASE 表達式里,也是順其自然的:
SELECT CASE WHEN count(city) = 100 THEN 1 WHEN sum(dau) > 200 THEN 2 ELSE 0 END AS abc FROM test
只要 SQL 表達式中存在聚合函數(shù),那么整個表達式都聚合了,此時訪問非聚合變量沒有任何意義。所以上面的例子,即便在 CASE 表達式中使用了聚合,其實也不過是聚合了一次后,按照條件進行判斷罷了。
這個特性可以解決很多實際問題,比如將一些復雜聚合判斷條件的結果用 SQL 結構輸出,那么很可能是下面這種寫法:
SELECT CASE WHEN 聚合函數(shù)(字段) 符合什么條件 THEN xxx ... 可能有 N 個 ELSE NULL END AS abc FROM test
這也可以認為是一種行轉列的過程,即 把行聚合后的結果通過一條條 CASE 表達式形成一個個新的列。
聚合與非聚合不能混用
我們希望利用 CASE 表達式找出那些 pv 大于平均值的行,以下這種想當然的寫法是錯誤的:
SELECT CASE WHEN pv > avg(pv) THEN 'yes' ELSE 'no' END AS abc FROM test
原因是,只要 SQL 中存在聚合表達式,那么整條 SQL 就都是聚合的,所以返回的結果只有一條,而我們期望查詢結果不聚合,只是判斷條件用到了聚合結果,那么就要使用子查詢。
為什么子查詢可以解決問題?因為子查詢的聚合發(fā)生在子查詢,而不影響當前父查詢,理解了這一點,就知道為什么下面的寫法才是正確的了:
SELECT CASE WHEN pv > ( SELECT avg(pv) from test ) THEN 'yes' ELSE 'no' END AS abc FROM test
這個例子也說明了 CASE 表達式里可以使用子查詢,因為子查詢是先計算的,所以查詢結果在哪兒都能用,CASE 表達式也不例外。
WHERE 中的 CASE
WHERE 后面也可以跟 CASE 表達式的,用來做一些需要特殊枚舉處理的篩選。
比如下面的例子:
SELECT * FROM demo WHERE CASE WHEN city = '北京' THEN true ELSE ID > 5 END
本來我們要查詢 ID 大于 5 的數(shù)據(jù),但我想對北京這個城市特別對待,那么就可以在判斷條件中再進行 CASE 分支判斷。
這個場景在 BI 工具里等價于,創(chuàng)建一個 CASE 表達式字段,可以拖入篩選條件生效。
GROUP BY 中的 CASE
想不到吧,GROUP BY 里都可以寫 CASE 表達式:
SELECT isPower, sum(gdp) FROM test GROUP BY CASE WHEN isPower = 1 THEN city, area ELSE city END
上面例子表示,計算 GDP 時,對于非常發(fā)達的城市,按照每個區(qū)粒度查看聚合結果,也就是看的粒度更細一些,而對于欠發(fā)達地區(qū),本身 gdp 也不高,直接按照城市粒度看聚合結果。
這樣,就按照不同的條件對數(shù)據(jù)進行了分組聚合。由于返回行結果是混在一起的,像這個例子,可以根據(jù) isPower 字段是否為 1 判斷,是否按照城市、區(qū)域進行了聚合,如果沒有其他更顯著的標識,可能導致無法區(qū)分不同行的聚合粒度,因此謹慎使用。
ORDER BY 中的 CASE
同樣,ORDER BY 使用 CASE 表達式,會將排序結果按照 CASE 分類進行分組,每組按照自己的規(guī)則排序,比如:
SELECT * FROM test ORDER BY CASE WHEN isPower = 1 THEN gdp ELSE people END
上面的例子,對發(fā)達地區(qū)采用 gdp 排序,否則采用人口數(shù)量排序。
總結
CASE 表達式總結一下有如下特點:
- 支持簡單與搜索兩種寫法,推薦搜索寫法。
- 支持聚合與子查詢,需要注意不同情況的特點。
- 可以寫在 SQL 查詢的幾乎任何地方,只要是可以寫字段的地方,基本上就可以替換為 CASE 表達式。
- 除了 SELECT 外,CASE 表達式還廣泛應用在 INSERT 與 UPDATE,其中 UPDATE 的妙用是不用將 SQL 拆分為多條,所以不用擔心數(shù)據(jù)變更后對判斷條件的二次影響。
原文鏈接:https://juejin.cn/post/7077358417643307039
相關推薦
- 2022-12-06 python中讀取txt文件時split()函數(shù)的妙用_python
- 2022-06-13 docker從安裝入門到應用部署及私有倉庫搭建基礎命令_docker
- 2022-09-06 一文詳解Python如何優(yōu)雅地對數(shù)據(jù)進行分組_python
- 2022-08-15 python中sort()和sorted()的區(qū)別及用法實例_python
- 2023-02-14 Python實現(xiàn)完全數(shù)的示例詳解_python
- 2022-10-25 Python條件語句的使用_python
- 2022-06-16 利用Jetpack?Compose實現(xiàn)繪制五角星效果_Android
- 2022-06-26 R語言實現(xiàn)PCA主成分分析圖的示例代碼_R語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支