概述:
sql語句中的case語句與高級語言中的switch語句更卒,是標(biāo)準(zhǔn)sql的語法,適用于一個條件判斷有多種值的情況下分別執(zhí)行不同的操作稚照。
首先蹂空,讓我們看一下CASE的語法。在一般的SELECT中果录,其語法格式如下:
CASE <單值表達(dá)式>
WHEN <表達(dá)式值> THEN <SQL語句或者返回值>
WHEN <表達(dá)式值> THEN <SQL語句或者返回值>
...
WHEN <表達(dá)式值> THEN <SQL語句或者返回值>
ELSE <SQL語句或者返回值>
END
★ 第一部分
創(chuàng)建一個用戶表
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL auto_increment,
`sex` tinyint(1) default 1 COMMENT '性別:0女上枕;1男;2保密',
`age` int(3) default 1 COMMENT '年齡',
`province` char(254) default NULL COMMENT '所在省份',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
向表中插入測試數(shù)據(jù)
INSERT INTO user(sex,age,province) VALUES
('1','22','北京'),
('0','25','廣東'),
('0','56','天津'),
('1','14','北京'),
('0','36','廣東'),
('1','68','湖南'),
('1','45','北京'),
('1','17','河北'),
('2','33','天津'),
('1','27','湖南'),
('1','29','北京'),
('2','70','廣東'),
('0','24','北京')
數(shù)據(jù)表如下圖:
實(shí)驗(yàn)1.1:將用戶性別用文字直觀顯示
1.簡單Case函數(shù)寫法(注意sex的位置)
select *,(CASE sex WHEN '1' THEN '男' WHEN '0' THEN '女' ELSE '保密' END) as sex_text
from user
2.Case搜索函數(shù)寫法(注意sex的位置【推薦】)
select *,(CASE WHEN sex='1' THEN '男' WHEN sex='0' THEN '女' ELSE '保密' END) as sex_text
from user
總結(jié):簡單Case函數(shù)寫法只適合相等條件判斷弱恒,不能用于大于辨萍、小于及不等于的判斷,
Case搜索函數(shù)寫法適合復(fù)雜條件判斷:可用于大于返弹、小于及不等于的判斷锈玉。
實(shí)驗(yàn)1.2:將用戶性別用文字直觀顯示:0女;1男义起;2保密拉背;并按性別顯示排序
select *,(CASE WHEN sex='1' THEN '男' WHEN sex='0' THEN '女' ELSE '保密' END) as sex_text
from user
order by sex_text DESC
總結(jié):用臨時生成的字段是可以排序的,MySQL查詢流程:先對表數(shù)據(jù)查詢默终,查出數(shù)據(jù)后再排序顯示椅棺。
實(shí)驗(yàn)1.3:將用戶年齡用文字直觀顯示(涉及數(shù)值范圍判斷,只能使用“Case搜索函數(shù)”寫法)齐蔽,如下:
select *,(CASE WHEN age>=60 THEN '老年' WHEN age<60 AND age>=30 THEN '中年' WHEN age<30 AND age>=18 THEN '青年' ELSE '未成年' END) as age_text
from user
實(shí)驗(yàn)1.4:綜合上面兩實(shí)驗(yàn)
select *,
(CASE WHEN sex='1' THEN '男' WHEN sex='0' THEN '女' ELSE '保密' END) as sex_text,
(CASE WHEN age>=60 THEN '老年' WHEN age<60 AND age>=30 THEN '中年' WHEN age<30 AND age>=18 THEN '青年' ELSE '未成年' END) as age_text
from user
實(shí)驗(yàn)1.5:將區(qū)域分組两疚,統(tǒng)計華北、華南分別的注冊人數(shù)
select count(*),(CASE province WHEN '北京' THEN '華北' WHEN '天津' THEN '華北' WHEN '河北' THEN '華北' WHEN '廣東' THEN '華南' WHEN '湖南' THEN '華南' END) as area
from user
group by area
總結(jié):同樣道理肴熏,臨時生成的字段 area 是可以在查詢結(jié)束后鬼雀,用來做排序或分組的顷窒。
==========================================================================================
★ 第二部分
創(chuàng)建數(shù)據(jù)表
CREATE TABLE `dj_zt` (
`id` int(10) unsigned NOT NULL auto_increment,
`zt` char(254) default NULL,
`bs` char(254) default NULL,
`qylx_dm` char(254) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
插入測試數(shù)據(jù)
INSERT INTO dj_zt(zt, bs, qylx_dm) VALUES
('01','a','01'),
('02','b','02'),
('03','c','03'),
('11','d','03'),
('03',null,'04'),
('07','f','03'),
('12','g','02'),
('07','h','03'),
('11','i','03'),
('07','j','03'),
('11','k','04')
實(shí)驗(yàn)2.1:查詢dj_zt表狀態(tài)值(zt)為'07'或'11'蛙吏,當(dāng)條件為 qylx_dm = '03' 的所有記錄數(shù)源哩。
A:用CASE語句
select count(CASE a.zt WHEN '07' THEN a.bs END) + count(CASE a.zt WHEN '11' THEN a.bs END) as num
from dj_zt a
where a.qylx_dm = '03'
B:不用CASE語句
select count(*)
from dj_zt a
where a.qylx_dm = '03' and a.zt in ('07', '11')
結(jié)果:A、B兩組耗費(fèi)的代價一樣的鸦做,相比較B的寫法簡潔励烦,平局。
實(shí)驗(yàn)2.2: 分別查詢dj_zt表狀態(tài)為'07'和'11'且qylx_dm = '03'的所有記錄數(shù)泼诱。
A:用CASE語句
select count(CASE a.zt WHEN '07' THEN a.bs END) as num1,count(CASE a.zt WHEN '11' THEN a.bs END) as num2
from dj_zt a
where a.qylx_dm = '03'
B:不用CASE語句(寫了兩條語句坛掠,掃描表兩遍,效率明顯低下)
select count(*)
from dj_zt a
where a.qylx_dm = '03' and a.zt='07'
select count(*)
from dj_zt a
where a.qylx_dm = '03' and a.zt='11'
結(jié)果:B組代價明顯高出A組很多,執(zhí)行的效率比較低治筒。
總結(jié):CASE 和 IF的區(qū)別:
·在高級語言中屉栓,CASE的可以用IF來替代,但是在SQL中不行耸袜。
·CASE是SQL標(biāo)準(zhǔn)定義的友多,IF是數(shù)據(jù)庫系統(tǒng)的擴(kuò)展。
·CASE可以用于SQL語句和SQL存儲過程堤框、觸發(fā)器域滥,IF只能用于存儲過程和觸發(fā)器。
·在SQL過程和觸發(fā)器中蜈抓,用IF替代CASE代價都相當(dāng)?shù)母咂舸拢喈?dāng)?shù)穆闊y以實(shí)現(xiàn)沟使。
通過上面幾組實(shí)例可以看出委可,應(yīng)用CASE語句可以讓SQL變得簡潔高效,從而大大提高了執(zhí)行效率腊嗡。而且撤缴,CASE的使用一般不會引起性能(相比沒有用CASE的語句)低下,反而增加了操作的靈活性
◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆
★ 第三部分 IF語句的用法
? IF(expr1,expr2,expr3)
? IF(expr1,expr2,expr3)
規(guī)則:如果 expr1 是TRUE叽唱,則返回expr2屈呕, 否則返回expr3。
IF() 的返回值為數(shù)字值或字符串值棺亭,具體情況視其所在語境而定虎眨。
實(shí)驗(yàn)3.1:如下:
select *,IF(sex='1','男','非男') as sex_text
from user
總結(jié):IF不像CASE那樣可以多條件判斷,IF只能判斷“真”镶摘、“假”嗽桩;
mysql> SELECT IF(1>2,2,3);
-> 3
mysql> SELECT IF(1<2,'yes ','no');
-> 'yes'
mysql> SELECT IF(STRCMP('test','test1'),'no','yes');
-> 'no'
如果expr2 或expr3中只有一個明確是 NULL,則IF() 函數(shù)的結(jié)果類型 為非NULL表達(dá)式的結(jié)果類型凄敢。
expr1 作為一個整數(shù)值進(jìn)行計算碌冶,就是說,假如你正在驗(yàn)證浮點(diǎn)值或字符串值涝缝, 那么應(yīng)該使用比較運(yùn)算進(jìn)行檢驗(yàn)扑庞。
mysql> SELECT IF(0.1,1,0);
-> 0
mysql> SELECT IF(0.1<>0,1,0);
-> 1
在所示的第一個例子中譬重,IF(0.1)的返回值為0,原因是 0.1 被轉(zhuǎn)化為整數(shù)值罐氨,從而引起一個對 IF(0)的檢驗(yàn)臀规。這或許不是你想要的情況。在第二個例子中栅隐,比較檢驗(yàn)了原始浮點(diǎn)值塔嬉,目的是為了了解是否其為非零值。比較結(jié)果使用整數(shù)租悄。
? IFNULL(expr1,expr2)
規(guī)則:假如 expr1 不為 NULL谨究,就返回 expr1,否則返回 expr2泣棋。
IFNULL()的返回值是數(shù)字或是字符串记盒,具體情況取決于其所使用的語境。
實(shí)驗(yàn)3.2:如果字段bs為空就返回字段zt的值
select *,IFNULL(bs,zt)
from dj_zt
where id in (5,6,12)
實(shí)驗(yàn)3.3:如果字段bs為空就返回'ZZX'
select *,IFNULL(bs,'ZZX')
from dj_zt
where id in (5,6,12)
mysql> SELECT IFNULL(1,0);
-> 1
mysql> SELECT IFNULL(NULL,10);
-> 10
mysql> SELECT IFNULL(1/0,10);
-> 10
mysql> SELECT IFNULL(1/0,'yes');
-> 'yes'
IFNULL(expr1,expr2)的默認(rèn)結(jié)果值為兩個表達(dá)式中更加“通用”的一個外傅,順序?yàn)镾TRING纪吮、 REAL或 INTEGER。假設(shè)一個基于表達(dá)式的表的情況萎胰, 或MySQL必須在內(nèi)存儲器中儲存一個臨時表中IFNULL()的返回值:
? NULLIF(expr1,expr2)
規(guī)則:如果 expr1 = expr2 成立碾盟,那么返回值為NULL,否則返回值為 expr1技竟。
這和CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END相同冰肴。
實(shí)驗(yàn)3.4:如果字段zt 與 字段qylx_dm有相等的值,就返回空榔组,否則返回zt
select *,NULLIF(zt,qylx_dm)
from dj_zt
mysql> SELECT NULLIF(1,1);
-> NULL
mysql> SELECT NULLIF(1,2);
-> 1
注意熙尉,如果參數(shù)不相等,則 MySQL 兩次求得的值為 expr1
轉(zhuǎn)載自:https://www.cnblogs.com/martinzhang/p/3220595.html