[資料庫] Oracle使用CASE判斷解決多值問題
阿新 • • 發佈:2019-01-05
這是最近在使用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)表示人的姓名和性別。
通常使用 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', '省示範、國家特色', '無')
方法二:使用case語句
相關知識
例如需要判斷職員的工資小於或等於2000元時,返回訊息“過低”,大於或等於4000時返回訊息“過高”,其餘返回“正常”。
這種需求通常會遇到,此時需要使用CASE WHEN來判斷轉換,程式碼如下所示:
再舉個例子,下面SQL程式碼是統計各個學位的職工人數:
表示當最高學歷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程式碼如下所示:
如果需要增加專業的其他資訊,如“專業程式碼”,如下程式碼所示:
進階篇
假設現在存在一張專業表ZY,僅僅儲存專業名稱和專業程式碼,需要通過連線兩張表ZY(專業表)和ZY_TAB(優勢專業表)來統計各專業的優勢專業資訊,怎麼處理呢?
ZY(NAME,CODE,INFO,PLACE)對應(專業名稱,專業程式碼,資訊,位置)。
因為通常資料庫設計中,都會設定專業表,再通過外來鍵來關聯其他的專業資訊,包括優勢專業、專業老師情況、專業學生情況、教學情況等等,所以通常需要通過ZY_CODE專業程式碼來進行關聯。
最後希望文章對你有所幫助,主要講述了使用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,
(select
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
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/)