select case when if 的一些用法
概述:
sql語句中的case語句與高級語言中的switch語句,是標准sql的語法,適用於一個條件判斷有多種值的情況下分別執行不同的操作。
首先,讓我們看一下CASE的語法。在一般的SELECT中,其語法格式如下:
CASE <單值表達式>
WHEN <表達式值> THEN <SQL語句或者返回值>
WHEN <表達式值> THEN <SQL語句或者返回值>
...
WHEN <表達式值> THEN <SQL語句或者返回值>
ELSE <SQL語句或者返回值>
END
★ 第一部分
# 創建一個用戶表
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
# 向表中插入測試數據
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','北京')
數據表如下圖:
------------------------------------------------------------------------------------------
實驗1.1:將用戶性別用文字直觀顯示
1.簡單Case函數寫法(注意sex的位置)
select *,(CASE sex WHEN '1' THEN '男' WHEN '0' THEN '女' ELSE '保密' END) as sex_text
from user
2.Case搜索函數寫法(注意sex的位置【推薦】)
select *,(CASE WHEN sex='1' THEN '男' WHEN sex='0' THEN '女' ELSE '保密' END) as sex_text
from user
總結:簡單Case函數寫法只適合相等條件判斷,不能用於大於、小於及不等於的判斷,
Case搜索函數寫法適合復雜條件判斷:可用於大於、小於及不等於的判斷。
------------------------------------------------------------------------------------------
實驗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
總結:用臨時生成的字段是可以排序的,MySQL查詢流程:先對表數據查詢,查出數據后再排序顯示。
------------------------------------------------------------------------------------------
實驗1.3:將用戶年齡用文字直觀顯示(涉及數值范圍判斷,只能使用“Case搜索函數”寫法),如下:
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
------------------------------------------------------------------------------------------
實驗1.4:綜合上面兩實驗
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
------------------------------------------------------------------------------------------
實驗1.5:將區域分組,統計華北、華南分別的注冊人數
select count(*),(CASE province WHEN '北京' THEN '華北' WHEN '天津' THEN '華北' WHEN '河北' THEN '華北' WHEN '廣東' THEN '華南' WHEN '湖南' THEN '華南' END) as area
from user
group by area
總結:同樣道理,臨時生成的字段 area 是可以在查詢結束后,用來做排序或分組的。
==========================================================================================
★ 第二部分
# 創建數據表
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
# 插入測試數據
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')
實驗2.1:查詢dj_zt表狀態值(zt)為'07'或'11',當條件為 qylx_dm = '03' 的所有記錄數。
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')
結果:A、B兩組耗費的代價一樣的,相比較B的寫法簡潔,平局。
------------------------------------------------------------------------------------------
實驗2.2: 分別查詢dj_zt表狀態為'07'和'11'且qylx_dm = '03'的所有記錄數。
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'
結果:B組代價明顯高出A組很多,執行的效率比較低。
總結:CASE 和 IF的區別:
·在高級語言中,CASE的可以用IF來替代,但是在SQL中不行。
·CASE是SQL標准定義的,IF是數據庫系統的擴展。
·CASE可以用於SQL語句和SQL存儲過程、觸發器,IF只能用於存儲過程和觸發器。
·在SQL過程和觸發器中,用IF替代CASE代價都相當的高,相當的麻煩,難以實現。
通過上面幾組實例可以看出,應用CASE語句可以讓SQL變得簡潔高效,從而大大提高了執行效率。而且,CASE的使用一般不會引起性能(相比沒有用CASE的語句)低下,反而增加了操作的靈活性
◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆
★ 第三部分 IF語句的用法
▶ IF(expr1,expr2,expr3)
規則:如果 expr1 是TRUE,則返回expr2, 否則返回expr3。
IF() 的返回值為數字值或字符串值,具體情況視其所在語境而定。
實驗3.1:如下:
select *,IF(sex='1','男','非男') as sex_text
from user
總結: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() 函數的結果類型 為非NULL表達式的結果類型。
expr1 作為一個整數值進行計算,就是說,假如你正在驗證浮點值或字符串值, 那么應該使用比較運算進行檢驗。
mysql> SELECT IF(0.1,1,0);
-> 0
mysql> SELECT IF(0.1<>0,1,0);
-> 1
在所示的第一個例子中,IF(0.1)的返回值為0,原因是 0.1 被轉化為整數值,從而引起一個對 IF(0)的檢驗。這或許不是你想要的情況。在第二個例子中,比較檢驗了原始浮點值,目的是為了了解是否其為非零值。比較結果使用整數。
------------------------------------------------------------------------------------------
▶ IFNULL(expr1,expr2)
規則:假如 expr1 不為 NULL,就返回 expr1,否則返回 expr2。
IFNULL()的返回值是數字或是字符串,具體情況取決於其所使用的語境。
實驗3.2:如果字段bs為空就返回字段zt的值
select *,IFNULL(bs,zt)
from dj_zt
where id in (5,6,12)
實驗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)的默認結果值為兩個表達式中更加“通用”的一個,順序為STRING、 REAL或 INTEGER。假設一個基於表達式的表的情況, 或MySQL必須在內存儲器中儲存一個臨時表中IFNULL()的返回值:
------------------------------------------------------------------------------------------
▶ NULLIF(expr1,expr2)
規則:如果 expr1 = expr2 成立,那么返回值為NULL,否則返回值為 expr1。
這和CASE WHEN expr1 = expr2 THEN NULL ELSE expr1 END相同。
實驗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
注意,如果參數不相等,則 MySQL 兩次求得的值為 expr1