第一章 神奇的sql 1-1 CASE表达式

语句分析

这两种写法的执行结果是相同的,
“sex”列(字段)如果是 ‘1’,那
么结果为男;如果是 ‘2’,那么结果为女。
简单 CASE 表达式正如其名,写法简单,但能实现的事情比较有限。
简单 CASE 表达式能写的条件,搜索CASE 表达式也能写,所以本书基本上采用搜索 CASE 表达式的写法。

#CASE 表达式的写法
#简单 CASE 表达式
SELECT
case
	sex 
	WHEN '1' THEN
	'男' 
	WHEN '2' THEN
	'女' ELSE '其他' 
END 
FROM
	casepopulation;

运行结果:
在这里插入图片描述

在发现为真的 WHEN 子句时,
CASE 表达式的真假值判断就会中止,而剩余的 WHEN 子句会被忽略。
为了避免引起不必要的混乱,使用 WHEN 子句时要注意条件的排他性。

■剩余的 WHEN 子句被忽略的写法示例
-- 例如,这样写的话,结果里不会出现“第二”
SELECT
CASE
WHEN
	sex IN ( '1','2' ) THEN
	'第一' 
	WHEN sex IN ( '2' ) THEN
	'第二' ELSE '其他' 
END 
FROM
	casepopulation;

运行结果:
在这里插入图片描述

使用 CASE 表达式的时候,还需要注意以下几点

  • 注意事项 1:统一各分支返回的数据类型
    虽然这一点无需多言,但这里还是要强调一下:
    一定要注意 CASE 表达式里各个分支返回的数据类型是否一致。
    某个分支返回字符型,而其他分支返回数值型的写法是不正确的

- 注意事项 2:不要忘了写 END

使用 CASE 表达式的时候,最容易出现的语法错误是忘记写 END。

- 注意事项 3:养成写 ELSE 子句的习惯

与 END 不同,ELSE 子句是可选的,不写也不会出错。
不写 ELSE 子句时,CASE 表达式的执行结果是 NULL。
但是不写可能会造成“语法没有错误,结果却不对”这种不易追查原因的麻烦,所以最好明确地写上 ELSE 子句(即便是在结果可以为 NULL 的情况下)。
养成这样的习惯后,我们从代码上就可以清楚地看到这种条件下会生成 NULL,而且将来代码有修改时也能减少失误。

将已有编号方式转换为新的方式并统计

#统计结果
SELECT
CASE
	pref_name 
	WHEN '得到' THEN
	'华南' 
	WHEN '香川' THEN
	'华西' 
	WHEN '徐州' THEN
	'华中' 
	WHEN '北京' THEN
	'华北' ELSE '其他' 
	END as district,
	SUM( population ) as '人口'
FROM
	casepopulation 
GROUP BY district;
	
	
#查询人数
SELECT 
CASE WHEN population < 100 THEN '01'
WHEN population >= 100 AND  population <200 THEN '02'
WHEN population >= 200 AND  population <300 THEN '03'
WHEN population >= 300 THEN '04'
ELSE NULL END AS pop_class,
count(1) as cnt
FROM casepopulation
GROUP BY pop_class;

没错,这里的 GROUP BY 子句使用的正是 SELECT 子句里定义的列的别称——district。
但是严格来说,这种写法是违反标准 SQL 的规则的。
因为 GROUP BY 子句比 SELECT 语句先执行,所以在 GROUP BY 子句中引
用在 SELECT 子句里定义的别称是不被允许的。
事实上,在 Oracle、DB2、SQL Server 等数据库里采用这种写法时就会出错。
不过也有支持这种 SQL 语句的数据库,
例如在 PostgreSQL 和 MySQL中,这个查询语句就可以顺利执行。这是因为,这些数据库在执行查询语句时,会先对 SELECT 子句里的列表进行扫描,并对列进行计算。
不过因为这是违反标准的写法,所以这里不强烈推荐大家使用。
但是,这样写出来的 SQL 语句确实非常简洁,而且可读性也很好

表之间的数据匹配

sql表语句地址
在这里插入图片描述

#1-1-课程
-- 表的匹配 :使用 IN 谓词
SELECT
	course_name,
CASE
	WHEN course_id IN ( SELECT course_id FROM opencourses WHERE month = '200706' ) THEN
	'O' ELSE 'x' 
	END AS "6月",
CASE
	WHEN course_id IN ( SELECT course_id FROM opencourses WHERE month = '200707' ) THEN
	'O' ELSE 'x' 
	END AS "7月",
CASE
	WHEN course_id IN ( SELECT course_id FROM opencourses WHERE month = '200708' ) THEN
	'O' ELSE 'x' 
	END AS "8月" 
FROM
	coursemaster;
	
	
-- 表的匹配 :使用 EXISTS 谓词
SELECT
	cm.course_name,
CASE
	WHEN EXISTS ( SELECT course_id FROM opencourses oc WHERE MONTH = '200706' AND oc.course_id = cm.course_id ) THEN
	'O' ELSE 'X' 
	END AS '6月',
CASE
	WHEN EXISTS ( SELECT course_id FROM opencourses oc WHERE MONTH = '200707' AND oc.course_id = cm.course_id ) THEN
	'O' ELSE 'X' 
	END AS '7月',
CASE
	WHEN EXISTS ( SELECT course_id FROM opencourses oc WHERE MONTH = '200708' AND oc.course_id = cm.course_id ) THEN
	'O' ELSE 'X' 
	END AS '8月' 
FROM
	coursemaster cm;

这样的查询没有进行聚合,因此也不需要排序,月份增加的时候仅修
改 SELECT 子句就可以了,扩展性比较好。
无论使用 IN 还是 EXISTS,得到的结果是一样的,但从性能方面来说,
EXISTS 更好。通过 EXISTS 进行的子查询能够用到“month, course_
id”这样的主键索引,因此尤其是当表 OpenCourses 里数据比较多的时候
更有优势

猜你喜欢

转载自blog.csdn.net/qq_35226176/article/details/89534386