SQL进阶:一、CASE表达式

  • 作为学习笔记存在

一、CASE表达式

-- 有两种表达式:
-- 表达式1
CASE gender 
	WHEN '1' THEN '男'
	WHEN '2' THEN '女'
	ELSE '未知性别' 
END AS 性别

-- 表达式2
CASE 
	WHEN gender = '1' THEN '男'
	WHEN gender = '2' THEN '女'
	ELSE '未知性别' 
END AS 性别

在CASE表达式里,可以使用BETEEN、LIKE和<,> ,IN等便利的谓词组合。

1.1 可以配合IN使用

-- 示例
CASE 
	WHEN city_name IN ('商丘','郑州') THEN '河南'
	WHEN city_name IN ('潍坊','淄博') THEN	'山东'
	ELSE '其它'
END

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

SELECT 
 CASE 
	 WHEN city_name IN ('郑州市','开封市','开封市','新乡市','周口市','商丘市') THEN '河南省' 
	 WHEN city_name IN ('南京市','无锡市','苏州市','常州市','南通市','扬州市') THEN '江苏省' 
	 ELSE '其他省份'
 END AS provinces ,
 sum(population) AS '总人口'
FROM poptbl p 
GROUP BY provinces;

1.3 将数值按照适当的级别进行分类统计

-- 按照人口数量等级查询市区个数。

SELECT 
	CASE 
		WHEN population < 100 THEN '低于100' 
		WHEN population >= 100 AND population < 200 THEN '大于100,小于200' 
		WHEN population >= 200 AND population < 300 THEN '大于200,小于300' 
		WHEN population >= 300  THEN '大于300' 
	END AS pop_class,
	count(*) 市区数量 
FROM poptbl p GROUP BY pop_class;

1.4 行转换列

poptbl2 数据:

IDcity_namegenderpopulation
2周口市1150
3周口市2110
4商丘市1230
5商丘市2220
6南京市190
7南京市2190
8无锡市1130
9无锡市2150
10常州市190
11常州市2190
12苏州市1320
13苏州市2310
-- 行转换列
SELECT
	city_name, 
	SUM(CASE WHEN gender = '1' THEN population ELSE	0 END) AS,
	SUM(CASE WHEN gender = '2' THEN population ELSE 0 END) ASFROM
	poptbl2 p
GROUP BY
	city_name ;

转换后的数据:

city_name
周口市150110
商丘市230220
南京市90190
无锡市130150
常州市90190
苏州市320310
  • 转换行列,在表头里加入汇总和再揭
SELECT 
 CASE 
 	WHEN gender = '1' THEN '男'
 	WHEN gender = '2' THEN '女'
 	ELSE '未知性别'
 END AS 性别,
 sum(population) AS 汇总,
 sum(CASE WHEN city_name = '周口市' THEN population ELSE 0 END ) AS '周口市',
 sum(CASE WHEN city_name = '商丘市' THEN population ELSE 0 END ) AS '商丘市',
 sum(CASE WHEN city_name = '南京市' THEN population ELSE 0 END ) AS '南京市',
 sum(CASE WHEN city_name = '无锡市' THEN population ELSE 0 END ) AS '无锡市',
 sum(CASE WHEN city_name = '常州市' THEN population ELSE 0 END ) AS '常州市',
 sum(CASE WHEN city_name = '苏州市' THEN population ELSE 0 END ) AS '苏州市',
 sum(CASE WHEN city_name IN ('周口市','商丘市') THEN population ELSE 0 END) AS  '河南'
 FROM 
 poptbl2 p GROUP BY gender ;

查询数据展示:

性别汇总周口市商丘市南京市无锡市常州市苏州市河南
10101502309013090320380
1170110220190150190310330

新手用WHERE子句进行条件分支,高手用SELECT子句进行条件分支

1.5 update 语句进行条件分支。使用CASE

原始数据:SELECT * FROM salaries s ;

IDnamesalary
1张三300000
2李四270000
3小红220000
4小李290000
5小北350000

需求:

  1. 对当前工资为30万元以上的员工,降薪10%。
  2. 对当前工资为25万元以上且不满28万元的员工,加薪20%。
UPDATE salaries SET salary = 
CASE
	WHEN salary >= 300000 THEN salary * 0.9
	WHEN salary >= 250000 AND salary < 280000 THEN salary * 1.2
	ELSE salary  -- 此处别忘写,如果不符合调薪的条件保持原工资,不写会改为null
END;

行sql后的数据:

IDnamesalary
1张三270000
2李四324000
3小红220000
4小李290000
5小北315000

1.6 CASE使用IN、EXISTS谓词

coursemaster原始数据:

course_idcourse_name
1马克思主义
2计算机科学与技术
3物理学
4生物学

opencourses原始数据:

monthcourse_id
2023051
2023053
2023054
2023064
2023072
2023074
  1. 把每个学科在5、6、7月份是否开课列出来。开课为O,不开课为X。

    -- 使用IN谓词
    SELECT course_name AS 课程名称,
    CASE 
    	WHEN course_id IN (SELECT course_id FROM opencourses o WHERE months = '202305') THEN 'O'
    	ELSE 'X'
    END AS '5月份',
    CASE 
    	WHEN course_id IN (SELECT course_id FROM opencourses o WHERE months = '202306') THEN 'O'
    	ELSE 'X'
    END AS '6月份',
    CASE 
    	WHEN course_id IN (SELECT course_id FROM opencourses o WHERE months = '202307') THEN 'O'
    	ELSE 'X'
    END AS '7月份'
    FROM coursemaster c ;
    
    -- 使用EXISTS谓词
    SELECT course_name AS '课程名称',
    CASE 
    	WHEN  EXISTS (SELECT course_id FROM opencourses o WHERE months = '202305' AND o.course_id = c.course_id) THEN 'O'
    	ELSE 'X'
    END AS '5月份',
    CASE 
    	WHEN  EXISTS (SELECT course_id FROM opencourses o WHERE months = '202306'  AND o.course_id = c.course_id) THEN 'O'
    	ELSE 'X'
    END AS '6月份',
    CASE 
    	WHEN  EXISTS (SELECT course_id FROM opencourses o WHERE months = '202307'  AND o.course_id = c.course_id) THEN 'O'
    	ELSE 'X'
    END AS '7月份'
    FROM coursemaster c ;
    

    查询数据展示:

    课程名称5月份6月份7月份
    马克思主义OXX
    计算机科学与技术XXO
    物理学OXX
    生物学OOO

1.7 在CASE表达式中使用聚合函数

studentClub 原数据。 main_club_flg设置Y或者N来表明哪一个社团是他的主社团标志。对于只加入了一个社团的学生,将其“主社团标志”设置为N。

std_idclub_idclub_namemain_club_flg
20230011棒球Y
20230012管弦乐N
20230022管弦乐N
20230023羽毛球Y
20230024足球N
20230034足球N
20230045游泳N
20230056围棋N
  1. 获取之加入了一个社团的学生的社团ID。
  2. 获取加入了多个社团的学生的主社团ID。
-- 经分析,都是获取学生的主社团ID。
SELECT  std_id,
CASE 
	WHEN count(*) = 1 THEN max(club_id) -- 只加入一个社团的学生
	ELSE max(CASE WHEN main_club_flg = 'Y' THEN club_id ELSE null END ) -- 加入多个社团的学生的主社团
END AS main_club
FROM studentclub s GROUP BY std_id ;

这句话要理解:如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中,也就是说查出来的列必须在group by后面出现否则就会报错,或者这个字段出现在聚合函数里面

查询出来的数据:

std_idmain_club
20230011
20230023
20230034
20230045
20230056
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杳杳明明

您的鼓励就是我的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值