[数据库] Oracle使用CASE判断解决多值问题
生活随笔
收集整理的這篇文章主要介紹了
[数据库] Oracle使用CASE判断解决多值问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? ? 這是最近在使用Oracle數據庫時的一個問題,個人認為是一個非常經典的問題。假設現在有一張專業表,包括如下信息:
? ? ? ? 其中表為:ZY_TAB(ZY_NAME,ZY_CODE,ZY_TYPE,ZY_TIME)。專業表中ZY_NAME表示專業名稱,ZY_CODE表示專業代碼,ZY_TYPE表示專業類型(包含國家特色專業和省示范專業),ZY_TIME表示設置國家特色專業或省級示范專業的時間。
? ? ? ? 例如軟件工程,2004年設為省示范專業,2012年升級為國家特色專業。現在需要輸出如下圖所示的表格:
? ? ? ? ?如果使用Java后臺處理,通常會將整個ZY_TAB內容讀取,然后依次對專業的ZY_TYPE(優勢專業)進行判斷,判斷主要包括三類:僅為“國家特色專業”,僅為“省示范專業”,同時為“國家特色專業”和“省示范專業”。
? ? ? ? 但是總感覺有些別扭,如果只用SQL語句進行解決,怎么處理呢?
? ? ? ? 方法一:decode函數
? ? ? ? 相關知識
? ? ? ? 首先想到的方法是使用decode函數判斷。
? ? ? ? decode(類型, '類型1', '值1', '類型2', '值2', '其它')
? ? ? ? 它的優勢是可以輸出自定義的值,例如:
? ? ? ? decode(sex, 'Man', '男', 'Woman', '女', '無')
? ? ? ? 先存在下表:PERSON(NAME,SEX)表示人的姓名和性別。
select NAME, DECODE(SEX, 'Man', '男', 'Woman', '女', '無') as SEX from PERSON;
? ? ? ? 通常使用 decode(b, 0, 0, a/b) 防止a/b中分母b為0報錯,它的具體含義是如果分母b為0,則SQL返回0,否則返回a/b,相當于執行除法操作。
? ? ? ? 再如重命名為自己喜歡的名稱,如null自定義命名:nvl(SEX,'定義為空'),它等價于 decode(SEX, NULL, '定義為空', SEX)。
? ? ? ? 具體操作
? ? ? ? 這里想使用:
? ? ? ? decode(count(ZY_TYPE), '1', '省示范專業', '2', '省示范、國家特色', '無')
select ZY_NAME, DECODE(count(ZY_NAME), '1', '省示范專業', '2', '省示范、國家特色專業', '無') as TYPE from ZY_TAB GROUP BY ZY_NAME; ? ? ? ? 輸出如下圖所示結果,其錯誤是當count(ZY_NAME)=1時,“國家特色專業”也變成了“省示范專業”,所以僅僅通過判斷出現的次數方法不太好。
? ? ? ?? 方法二:使用case語句
? ? ? ??相關知識
? ? ? ? 例如需要判斷職員的工資小于或等于2000元時,返回消息“過低”,大于或等于4000時返回消息“過高”,其余返回“正常”。
? ? ? ? 這種需求通常會遇到,此時需要使用CASE WHEN來判斷轉換,代碼如下所示:
select NAME, SEX, SAL, CASE WHEN SAL<=2000 THEN '過低'WHEN SAL>=4000 THEN '過高'ELSE '正常'END AS STATE from PERSON order by NAME; ? ? ? ? 輸出如下圖所示:
? ? ? ? 再舉個例子,下面SQL代碼是統計各個學位的職工人數: ?
SELECT COUNT(*) AS 總人數, COUNT(CASE WHEN HIGHEST_DEGREE='博士'THEN 1 END) AS 博士人數, COUNT(CASE WHEN HIGHEST_DEGREE='碩士'THEN 1 END) AS 碩士人數, COUNT(*)-COUNT(CASE WHEN HIGHEST_DEGREE='博士'THEN 1 END)-COUNT(CASE WHEN HIGHEST_DEGREE='碩士'THEN 1 END) AS 其他學歷 FROM TEACHER; ? ? ? ? COUNT(CASE WHEN HIGHEST_DEGREE='博士' THEN 1 END) AS NUM2
? ? ? ? 表示當最高學歷HIGHEST_DEGREE字段為'博士'時,統計數量加1。
? ? ? ? 當然如果需要計算學院各個班級的總人口,可以采用使用下面的SQL:
? ? ? ? COUNT(CASE WHEN DW_NAME='軟件學院' THEN NUM_STU END) AS NUM2
? ? ? ? 也可以使用提到的CASE防止除法計算分母為0,ZS總數、SHSJ社會實踐人數。即:
? ? ? ? round((case when ZS!=0 then SHSJ/ZS else 0 end),3) as bl
? ? ? ? 具體操作
? ? ? ? 此時需要使用CASE WHEN來判斷,這里使用了兩次CASE WHEN,第一次是判斷是“國家特色專業”或“省示范專業”,第二次是判斷該專業出現的次數,如果出現兩次則表示兩個類型都存在。
? ? ? ? 原始數據如下圖所示:
? ? ? ? SQL代碼如下所示:
select ZY_NAME, CASE WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' OR ZY_TYPE='國家特色專業' THEN 1 END)='2' THEN '省示范專業; 國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='國家特色專業' THEN 1 END)='1' THEN '國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' THEN 1 END)='1' THEN '省示范專業' ELSE NULL END AS TYPE from ZY_TAB group by ZY_NAME; ? ? ? ? 使用group by防止專業名稱重復,輸出結果如下圖所示:
? ? ? ? 如果需要增加專業的其他信息,如“專業代碼”,如下代碼所示:
select ZY_NAME, ZY_CODE, CASE WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' OR ZY_TYPE='國家特色專業' THEN 1 END)='2' THEN '省示范專業; 國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='國家特色專業' THEN 1 END)='1' THEN '國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' THEN 1 END)='1' THEN '省示范專業' ELSE NULL END AS TYPE from ZY_TAB group by ZY_NAME, ZY_CODE; ? ? ? ? group by 分組中增加ZY_CODE,輸出如下圖所示:
? ? ? ? 進階篇
? ? ? ? 假設現在存在一張專業表ZY,僅僅保存專業名稱和專業代碼,需要通過連接兩張表ZY(專業表)和ZY_TAB(優勢專業表)來統計各專業的優勢專業信息,怎么處理呢?
? ? ? ? ZY(NAME,CODE,INFO,PLACE)對應(專業名稱,專業代碼,信息,位置)。
? ? ? ? 因為通常數據庫設計中,都會設定專業表,再通過外鍵來關聯其他的專業信息,包括優勢專業、專業老師情況、專業學生情況、教學情況等等,所以通常需要通過ZY_CODE專業代碼來進行關聯。
select NAME, CODE, (selectCASE WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' OR ZY_TYPE='國家特色專業' THEN 1 END)='2' THEN '省示范專業; 國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='國家特色專業' THEN 1 END)='1' THEN '國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' THEN 1 END)='1' THEN '省示范專業' ELSE NULL END from ZY_TAB where ZY_TAB.ZY_CODE=ZY.CODE) AS TYPE, INFO, PLACE from ZY; ? ? ? ? 輸出如下圖所示:
? ? ? ? 最后希望文章對你有所幫助,主要講述了使用DECODE函數和CASE判斷多值問題,當然如果多個類型也是可以判斷并多指輸出的,但建議通常判斷該兩個類型,要么輸出A,要么輸出B,要么輸出A和B。
? ? ? ? 還是那句話,數據庫相關的知識,只有當你真正遇到這個需求的時候對你幫助才會非常大,否則你也可以把它當成簡單基礎知識回顧。
? ? ? (By:Eastmount 2016-7-20 晚上8點 ??http://blog.csdn.net/eastmount/)
? ? ? ? 其中表為:ZY_TAB(ZY_NAME,ZY_CODE,ZY_TYPE,ZY_TIME)。專業表中ZY_NAME表示專業名稱,ZY_CODE表示專業代碼,ZY_TYPE表示專業類型(包含國家特色專業和省示范專業),ZY_TIME表示設置國家特色專業或省級示范專業的時間。
? ? ? ? 例如軟件工程,2004年設為省示范專業,2012年升級為國家特色專業。現在需要輸出如下圖所示的表格:
? ? ? ? ?如果使用Java后臺處理,通常會將整個ZY_TAB內容讀取,然后依次對專業的ZY_TYPE(優勢專業)進行判斷,判斷主要包括三類:僅為“國家特色專業”,僅為“省示范專業”,同時為“國家特色專業”和“省示范專業”。
? ? ? ? 但是總感覺有些別扭,如果只用SQL語句進行解決,怎么處理呢?
? ? ? ? 方法一:decode函數
? ? ? ? 相關知識
? ? ? ? 首先想到的方法是使用decode函數判斷。
? ? ? ? decode(類型, '類型1', '值1', '類型2', '值2', '其它')
? ? ? ? 它的優勢是可以輸出自定義的值,例如:
? ? ? ? decode(sex, 'Man', '男', 'Woman', '女', '無')
? ? ? ? 先存在下表:PERSON(NAME,SEX)表示人的姓名和性別。
select NAME, DECODE(SEX, 'Man', '男', 'Woman', '女', '無') as SEX from PERSON;
? ? ? ? 通常使用 decode(b, 0, 0, a/b) 防止a/b中分母b為0報錯,它的具體含義是如果分母b為0,則SQL返回0,否則返回a/b,相當于執行除法操作。
? ? ? ? 再如重命名為自己喜歡的名稱,如null自定義命名:nvl(SEX,'定義為空'),它等價于 decode(SEX, NULL, '定義為空', SEX)。
? ? ? ? 具體操作
? ? ? ? 這里想使用:
? ? ? ? decode(count(ZY_TYPE), '1', '省示范專業', '2', '省示范、國家特色', '無')
select ZY_NAME, DECODE(count(ZY_NAME), '1', '省示范專業', '2', '省示范、國家特色專業', '無') as TYPE from ZY_TAB GROUP BY ZY_NAME; ? ? ? ? 輸出如下圖所示結果,其錯誤是當count(ZY_NAME)=1時,“國家特色專業”也變成了“省示范專業”,所以僅僅通過判斷出現的次數方法不太好。
? ? ? ?? 方法二:使用case語句
? ? ? ??相關知識
? ? ? ? 例如需要判斷職員的工資小于或等于2000元時,返回消息“過低”,大于或等于4000時返回消息“過高”,其余返回“正常”。
? ? ? ? 這種需求通常會遇到,此時需要使用CASE WHEN來判斷轉換,代碼如下所示:
select NAME, SEX, SAL, CASE WHEN SAL<=2000 THEN '過低'WHEN SAL>=4000 THEN '過高'ELSE '正常'END AS STATE from PERSON order by NAME; ? ? ? ? 輸出如下圖所示:
? ? ? ? 再舉個例子,下面SQL代碼是統計各個學位的職工人數: ?
SELECT COUNT(*) AS 總人數, COUNT(CASE WHEN HIGHEST_DEGREE='博士'THEN 1 END) AS 博士人數, COUNT(CASE WHEN HIGHEST_DEGREE='碩士'THEN 1 END) AS 碩士人數, COUNT(*)-COUNT(CASE WHEN HIGHEST_DEGREE='博士'THEN 1 END)-COUNT(CASE WHEN HIGHEST_DEGREE='碩士'THEN 1 END) AS 其他學歷 FROM TEACHER; ? ? ? ? COUNT(CASE WHEN HIGHEST_DEGREE='博士' THEN 1 END) AS NUM2
? ? ? ? 表示當最高學歷HIGHEST_DEGREE字段為'博士'時,統計數量加1。
? ? ? ? 當然如果需要計算學院各個班級的總人口,可以采用使用下面的SQL:
? ? ? ? COUNT(CASE WHEN DW_NAME='軟件學院' THEN NUM_STU END) AS NUM2
? ? ? ? 也可以使用提到的CASE防止除法計算分母為0,ZS總數、SHSJ社會實踐人數。即:
? ? ? ? round((case when ZS!=0 then SHSJ/ZS else 0 end),3) as bl
? ? ? ? 具體操作
? ? ? ? 此時需要使用CASE WHEN來判斷,這里使用了兩次CASE WHEN,第一次是判斷是“國家特色專業”或“省示范專業”,第二次是判斷該專業出現的次數,如果出現兩次則表示兩個類型都存在。
? ? ? ? 原始數據如下圖所示:
? ? ? ? SQL代碼如下所示:
select ZY_NAME, CASE WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' OR ZY_TYPE='國家特色專業' THEN 1 END)='2' THEN '省示范專業; 國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='國家特色專業' THEN 1 END)='1' THEN '國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' THEN 1 END)='1' THEN '省示范專業' ELSE NULL END AS TYPE from ZY_TAB group by ZY_NAME; ? ? ? ? 使用group by防止專業名稱重復,輸出結果如下圖所示:
? ? ? ? 如果需要增加專業的其他信息,如“專業代碼”,如下代碼所示:
select ZY_NAME, ZY_CODE, CASE WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' OR ZY_TYPE='國家特色專業' THEN 1 END)='2' THEN '省示范專業; 國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='國家特色專業' THEN 1 END)='1' THEN '國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' THEN 1 END)='1' THEN '省示范專業' ELSE NULL END AS TYPE from ZY_TAB group by ZY_NAME, ZY_CODE; ? ? ? ? group by 分組中增加ZY_CODE,輸出如下圖所示:
? ? ? ? 進階篇
? ? ? ? 假設現在存在一張專業表ZY,僅僅保存專業名稱和專業代碼,需要通過連接兩張表ZY(專業表)和ZY_TAB(優勢專業表)來統計各專業的優勢專業信息,怎么處理呢?
? ? ? ? ZY(NAME,CODE,INFO,PLACE)對應(專業名稱,專業代碼,信息,位置)。
? ? ? ? 因為通常數據庫設計中,都會設定專業表,再通過外鍵來關聯其他的專業信息,包括優勢專業、專業老師情況、專業學生情況、教學情況等等,所以通常需要通過ZY_CODE專業代碼來進行關聯。
select NAME, CODE, (selectCASE WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' OR ZY_TYPE='國家特色專業' THEN 1 END)='2' THEN '省示范專業; 國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='國家特色專業' THEN 1 END)='1' THEN '國家特色專業' WHEN COUNT(CASE WHEN ZY_TYPE='省示范專業' THEN 1 END)='1' THEN '省示范專業' ELSE NULL END from ZY_TAB where ZY_TAB.ZY_CODE=ZY.CODE) AS TYPE, INFO, PLACE from ZY; ? ? ? ? 輸出如下圖所示:
? ? ? ? 最后希望文章對你有所幫助,主要講述了使用DECODE函數和CASE判斷多值問題,當然如果多個類型也是可以判斷并多指輸出的,但建議通常判斷該兩個類型,要么輸出A,要么輸出B,要么輸出A和B。
? ? ? ? 還是那句話,數據庫相關的知識,只有當你真正遇到這個需求的時候對你幫助才會非常大,否則你也可以把它當成簡單基礎知識回顧。
? ? ? (By:Eastmount 2016-7-20 晚上8點 ??http://blog.csdn.net/eastmount/)
總結
以上是生活随笔為你收集整理的[数据库] Oracle使用CASE判断解决多值问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [数据库] Oracle单表查询总数及百
- 下一篇: 《统计自然语言处理》读书笔记 一.基础知