數(shù)據(jù)庫中case的用法
數(shù)據(jù)庫中case的用法的用法你知道嗎?下面小編就跟你們詳細(xì)介紹下數(shù)據(jù)庫中case的用法的用法,希望對你們有用。
數(shù)據(jù)庫中case的用法的用法如下:
沒有,用case when 來代替就行了.
例如,下面的語句顯示中文年月
select getdate() as 日期,case month(getdate())
when 11 then '十一'
when 12 then '十二'
else substring('一二三四五六七八九十', month(getdate()),1)
end+'月' as 月份
=================================================
CASE 可能是 SQL 中被誤用最多的關(guān)鍵字之一。雖然你可能以前用過這個(gè)關(guān)鍵字來創(chuàng)建字段,但是它還具有更多用法。例如,你可以在 WHERE 子句中使用 CASE。
首先讓我們看一下 CASE 的語法。在一般的 SELECT 中,其語法如下:
復(fù)制代碼
SELECT <myColumnSpec> =
CASE
WHEN <A> THEN <somethingA>
WHEN <B> THEN <somethingB>
ELSE <somethingE>
END
復(fù)制代碼
在上面的代碼中需要用具體的參數(shù)代替尖括號(hào)中的內(nèi)容。下面是一個(gè)簡單的例子:
復(fù)制代碼
USE pubs
GO
SELECT
Title,
'Price Range' =
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END
FROM titles
ORDER BY price
GO
復(fù)制代碼
這是 CASE 的典型用法,但是使用 CASE 其實(shí)可以做更多的事情。比方說下面的 GROUP BY 子句中的 CASE:
復(fù)制代碼
SELECT 'Number of Titles', Count(*)
FROM titles
GROUP BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END
GO
復(fù)制代碼
你甚至還可以組合這些選項(xiàng),添加一個(gè) ORDER BY 子句,如下所示:
復(fù)制代碼
USE pubs
GO
SELECT
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END AS Range,
Title
FROM titles
GROUP BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END,
Title
ORDER BY
CASE
WHEN price IS NULL THEN 'Unpriced'
WHEN price < 10 THEN 'Bargain'
WHEN price BETWEEN 10 and 20 THEN 'Average'
ELSE 'Gift to impress relatives'
END,
Title
GO
復(fù)制代碼
注意,為了在 GROUP BY 塊中使用 CASE,查詢語句需要在 GROUP BY 塊中重復(fù) SELECT 塊中的 CASE 塊。
除了選擇自定義字段之外,在很多情況下 CASE 都非常有用。再深入一步,你還可以得到你以前認(rèn)為不可能得到的分組排序結(jié)果集。
四,根據(jù)條件有選擇的UPDATE。
例,有如下更新條件
?工資5000以上的職員,工資減少10%
?工資在2000到4600之間的職員,工資增加15%
很容易考慮的是選擇執(zhí)行兩次UPDATE語句,如下所示
復(fù)制代碼
--條件1
UPDATE Personnel
SET salary = salary * 0.9
WHERE salary >= 5000;
--條件2
UPDATE Personnel
SET salary = salary * 1.15
WHERE salary >= 2000 AND salary < 4600;
復(fù)制代碼
但是事情沒有想象得那么簡單,假設(shè)有個(gè)人工資5000塊。首先,按照條件1,工資減少10%,變成工資4500。接下來運(yùn)行第二個(gè)SQL時(shí)候,因?yàn)檫@個(gè)人的工資是4500在2000到4600的范圍之內(nèi),需增加15%,最后這個(gè)人的工資結(jié)果是5175,不但沒有減少,反而增加了。如果要是反過來執(zhí)行,那么工資4600的人相反會(huì)變成減少工資。暫且不管這個(gè)規(guī)章是多么荒誕,如果想要一個(gè)SQL 語句實(shí)現(xiàn)這個(gè)功能的話,我們需要用到Case函數(shù)。代碼如下:
復(fù)制代碼
UPDATE Personnel
SET salary = CASE WHEN salary >= 5000
THEN salary * 0.9
WHEN salary >= 2000 AND salary < 4600
THEN salary * 1.15
ELSE salary END;
復(fù)制代碼
這里要注意一點(diǎn),最后一行的ELSE salary是必需的,要是沒有這行,不符合這兩個(gè)條件的人的工資將會(huì)被寫成NUll,那可就大事不妙了。在Case函數(shù)中Else部分的默認(rèn)值是NULL,這點(diǎn)是需要注意的地方。
這種方法還可以在很多地方使用,比如說變更主鍵這種累活。
一般情況下,要想把兩條數(shù)據(jù)的Primary key,a和b交換,需要經(jīng)過臨時(shí)存儲(chǔ),拷貝,讀回?cái)?shù)據(jù)的三個(gè)過程,要是使用Case函數(shù)的話,一切都變得簡單多了。
p_key
col_1
col_2
a
1
張三
b
2
李四
c
3
王五
假設(shè)有如上數(shù)據(jù),需要把主鍵a和b相互交換。用Case函數(shù)來實(shí)現(xiàn)的話,代碼如下
復(fù)制代碼
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');
復(fù)制代碼
同樣的也可以交換兩個(gè)Unique key。需要注意的是,如果有需要交換主鍵的情況發(fā)生,多半是當(dāng)初對這個(gè)表的設(shè)計(jì)進(jìn)行得不夠到位,建議檢查表的設(shè)計(jì)是否妥當(dāng)。
五,兩個(gè)表數(shù)據(jù)是否一致的檢查。
Case函數(shù)不同于DECODE函數(shù)。在Case函數(shù)中,可以使用BETWEEN,LIKE,IS NULL,IN,EXISTS等等。比如說使用IN,EXISTS,可以進(jìn)行子查詢,從而 實(shí)現(xiàn)更多的功能。
下面具個(gè)例子來說明,有兩個(gè)表,tbl_A,tbl_B,兩個(gè)表中都有keyCol列?,F(xiàn)在我們對兩個(gè)表進(jìn)行比較,tbl_A中的keyCol列的數(shù)據(jù)如果在tbl_B的keyCol列的數(shù)據(jù)中可以找到, 返回結(jié)果'Matched',如果沒有找到,返回結(jié)果'Unmatched'。
要實(shí)現(xiàn)下面這個(gè)功能,可以使用下面兩條語句
復(fù)制代碼
--使用IN的時(shí)候
SELECT keyCol,
CASE WHEN keyCol IN ( SELECT keyCol FROM tbl_B )
THEN 'Matched'
ELSE 'Unmatched' END Label
FROM tbl_A;
--使用EXISTS的時(shí)候
SELECT keyCol,
CASE WHEN EXISTS ( SELECT * FROM tbl_B
WHERE tbl_A.keyCol = tbl_B.keyCol )
THEN 'Matched'
ELSE 'Unmatched' END Label
FROM tbl_A;
復(fù)制代碼
使用IN和EXISTS的結(jié)果是相同的。也可以使用NOT IN和NOT EXISTS,但是這個(gè)時(shí)候要注意NULL的情況。
六,在Case函數(shù)中使用合計(jì)函數(shù)
假設(shè)有下面一個(gè)表
學(xué)號(hào)(std_id)
課程ID(class_id)
課程名(class_name)
主修flag(main_class_flg)
100
1
經(jīng)濟(jì)學(xué)
Y
100
2
歷史學(xué)
N
200
2
歷史學(xué)
N
200
3
考古學(xué)
Y
200
4
計(jì)算機(jī)
N
300
4
計(jì)算機(jī)
N
400
5
化學(xué)
N
500
6
數(shù)學(xué)
N
有的學(xué)生選擇了同時(shí)修幾門課程(100,200)也有的學(xué)生只選擇了一門課程(300,400,500)。選修多門課程的學(xué)生,要選擇一門課程作為主修,主修flag里面寫入Y。只選擇一門課程的學(xué)生,主修flag為N(實(shí)際上要是寫入Y的話,就沒有下面的麻煩事了,為了舉例子,還請多多包含)。
現(xiàn)在我們要按照下面兩個(gè)條件對這個(gè)表進(jìn)行查詢
?只選修一門課程的人,返回那門課程的ID
?選修多門課程的人,返回所選的主課程ID
簡單的想法就是,執(zhí)行兩條不同的SQL語句進(jìn)行查詢。
條件1
--條件1:只選擇了一門課程的學(xué)生
SELECT std_id, MAX(class_id) AS main_class
FROM Studentclass
GROUP BY std_id
HAVING COUNT(*) = 1;
執(zhí)行結(jié)果1
STD_ID MAIN_class
------ ----------
300 4
400 5
500 6
條件2
--條件2:選擇多門課程的學(xué)生
SELECT std_id, class_id AS main_class
FROM Studentclass
WHERE main_class_flg = 'Y' ;
執(zhí)行結(jié)果2
STD_ID MAIN_class
------ ----------
100 1
200 3
如果使用Case函數(shù),我們只要一條SQL語句就可以解決問題,具體如下所示
復(fù)制代碼
SELECT std_id,
CASE WHEN COUNT(*) = 1 --只選擇一門課程的學(xué)生的情況
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;
復(fù)制代碼
運(yùn)行結(jié)果
STD_ID MAIN_class
------ ----------
100 1
200 3
300 4
400 5
500 6
通過在Case函數(shù)中嵌套Case函數(shù),在合計(jì)函數(shù)中使用Case函數(shù)等方法,我們可以輕松的解決這個(gè)問題。使用Case函數(shù)給我們帶來了更大的自由度。
最后提醒一下使用Case函數(shù)的新手注意不要犯下面的錯(cuò)誤
CASE col_1
WHEN 1 THEN 'Right'
WHEN NULL THEN 'Wrong'
END
在這個(gè)語句中When Null這一行總是返回unknown,所以永遠(yuǎn)不會(huì)出現(xiàn)Wrong的情況。因?yàn)檫@句可以替換成WHEN col_1 = NULL,這是一個(gè)錯(cuò)誤的用法,這個(gè)時(shí)候我們應(yīng)該選擇用WHEN col_1 IS NULL。