SQL CASE 表达式的具体使用


Posted in SQL Server onMarch 21, 2022

CASE 表达式分为简单表达式与搜索表达式,其中搜索表达式可以覆盖简单表达式的全部能力,我也建议只写搜索表达式,而不要写简单表达式。

简单表达式:

SELECT CASE city
WHEN '北京' THEN 1
WHEN '天津' THEN 2
ELSE 0
END AS abc
FROM test

搜索表达式:

SELECT CASE
WHEN city = '北京' THEN 1
WHEN city = '天津' THEN 2
ELSE 0
END AS abc
FROM test

明显可以看出,简单表达式只是搜索表达式 a = b 的特例,因为无法书写任何符号,只要条件换成 a > b 就无法胜任了,而搜索表达式不但可以轻松胜任,甚至可以写聚合函数。

CASE 表达式里的聚合函数

为什么 CASE 表达式里可以写聚合函数?

因为本身表达式就支持聚合函数,比如下面的语法,我们不会觉得奇怪:

SELECT sum(pv), avg(uv) from test

本身 SQL 就支持多种不同的聚合方式同时计算,所以将其用在 CASE 表达式里,也是顺其自然的:

SELECT CASE
WHEN count(city) = 100 THEN 1
WHEN sum(dau) > 200 THEN 2
ELSE 0
END AS abc
FROM test

只要 SQL 表达式中存在聚合函数,那么整个表达式都聚合了,此时访问非聚合变量没有任何意义。所以上面的例子,即便在 CASE 表达式中使用了聚合,其实也不过是聚合了一次后,按照条件进行判断罢了。

这个特性可以解决很多实际问题,比如将一些复杂聚合判断条件的结果用 SQL 结构输出,那么很可能是下面这种写法:

SELECT CASE
WHEN 聚合函数(字段) 符合什么条件 THEN xxx
... 可能有 N 个
ELSE NULL
END AS abc
FROM test

这也可以认为是一种行转列的过程,即 把行聚合后的结果通过一条条 CASE 表达式形成一个个新的列

聚合与非聚合不能混用

我们希望利用 CASE 表达式找出那些 pv 大于平均值的行,以下这种想当然的写法是错误的:

SELECT CASE
WHEN pv > avg(pv) THEN 'yes'
ELSE 'no'
END AS abc
FROM test

原因是,只要 SQL 中存在聚合表达式,那么整条 SQL 就都是聚合的,所以返回的结果只有一条,而我们期望查询结果不聚合,只是判断条件用到了聚合结果,那么就要使用子查询。

为什么子查询可以解决问题?因为子查询的聚合发生在子查询,而不影响当前父查询,理解了这一点,就知道为什么下面的写法才是正确的了:

SELECT CASE
WHEN pv > ( SELECT avg(pv) from test ) THEN 'yes'
ELSE 'no'
END AS abc
FROM test

这个例子也说明了 CASE 表达式里可以使用子查询,因为子查询是先计算的,所以查询结果在哪儿都能用,CASE 表达式也不例外。

WHERE 中的 CASE

WHERE 后面也可以跟 CASE 表达式的,用来做一些需要特殊枚举处理的筛选。

比如下面的例子:

SELECT * FROM demo WHERE
CASE
WHEN city = '北京' THEN true
ELSE ID > 5
END

本来我们要查询 ID 大于 5 的数据,但我想对北京这个城市特别对待,那么就可以在判断条件中再进行 CASE 分支判断。

这个场景在 BI 工具里等价于,创建一个 CASE 表达式字段,可以拖入筛选条件生效。

GROUP BY 中的 CASE

想不到吧,GROUP BY 里都可以写 CASE 表达式:

SELECT isPower, sum(gdp) FROM test GROUP BY CASE
WHEN isPower = 1 THEN city, area
ELSE city
END

上面例子表示,计算 GDP 时,对于非常发达的城市,按照每个区粒度查看聚合结果,也就是看的粒度更细一些,而对于欠发达地区,本身 gdp 也不高,直接按照城市粒度看聚合结果。

这样,就按照不同的条件对数据进行了分组聚合。由于返回行结果是混在一起的,像这个例子,可以根据 isPower 字段是否为 1 判断,是否按照城市、区域进行了聚合,如果没有其他更显著的标识,可能导致无法区分不同行的聚合粒度,因此谨慎使用。

ORDER BY 中的 CASE

同样,ORDER BY 使用 CASE 表达式,会将排序结果按照 CASE 分类进行分组,每组按照自己的规则排序,比如:

SELECT * FROM test ORDER BY CASE
WHEN isPower = 1 THEN gdp
ELSE people
END

上面的例子,对发达地区采用 gdp 排序,否则采用人口数量排序。

总结

CASE 表达式总结一下有如下特点:

  • 支持简单与搜索两种写法,推荐搜索写法。
  • 支持聚合与子查询,需要注意不同情况的特点。
  • 可以写在 SQL 查询的几乎任何地方,只要是可以写字段的地方,基本上就可以替换为 CASE 表达式。
  • 除了 SELECT 外,CASE 表达式还广泛应用在 INSERT 与 UPDATE,其中 UPDATE 的妙用是不用将 SQL 拆分为多条,所以不用担心数据变更后对判断条件的二次影响。

到此这篇关于SQL CASE 表达式的具体使用的文章就介绍到这了,更多相关SQL CASE 表达式内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

SQL Server 相关文章推荐
2021-4-5课程——SQL Server查询【3】
Apr 05 SQL Server
SQL Server 数据库实验课第五周——常用查询条件
Apr 05 SQL Server
SqlServer: 如何更改表的文件组?(进而改变存储位置)
Apr 05 SQL Server
SQL SERVER中常用日期函数的具体使用
Apr 08 SQL Server
SQLServer 错误: 15404,无法获取有关 Windows NT 组/用户 WIN-8IVSNAQS8T7\Administrator 的信息
Jun 30 SQL Server
SQLServer之常用函数总结详解
Aug 30 SQL Server
sql server删除前1000行数据的方法实例
Aug 30 SQL Server
详解在SQLPlus中实现上下键翻查历史命令的功能
Mar 18 SQL Server
SQL Server远程连接的设置步骤(图文)
Mar 23 SQL Server
SQL Server #{}可以防止SQL注入
May 11 SQL Server
SQL Server数据库备份和恢复数据库的全过程
Jun 14 SQL Server
SQL Server数据库基本概念、组成、常用对象与约束
Mar 20 #SQL Server
详解在SQLPlus中实现上下键翻查历史命令的功能
Mar 18 #SQL Server
SQL Server实现分页方法介绍
Mar 16 #SQL Server
SQL Server中常用截取字符串函数介绍
Mar 16 #SQL Server
通过T-SQL语句创建游标与实现数据库加解密功能
Mar 16 #SQL Server
MySQL 中如何归档数据的实现方法
SQL Server查询某个字段在哪些表中存在
Mar 03 #SQL Server
You might like
调试PHP程序的多种方法介绍
2014/11/06 PHP
PHP采用get获取url汉字出现乱码的解决方法
2014/11/13 PHP
从刷票了解获得客户端IP的方法
2015/09/21 PHP
学习php设计模式 php实现策略模式(strategy)
2015/12/07 PHP
WordPress中获取页面链接和标题的相关PHP函数用法解析
2015/12/17 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
php语言注释,单行注释和多行注释
2018/01/21 PHP
JQuery 无废话系列教程(一) jquery入门 [推荐]
2009/06/23 Javascript
学习从实践开始之jQuery插件开发 菜单插件开发
2012/05/03 Javascript
js判断滚动条是否已到页面最底部或顶部实例
2014/11/20 Javascript
jQuery热气球动画半透明背景的后台登录界面代码分享
2015/08/28 Javascript
简单谈谈node.js 版本控制 nvm和 n
2015/10/15 Javascript
javascript中window.open在原来的窗口中打开新的窗口(不同名)
2015/11/15 Javascript
jquery插件jquery.dragscale.js实现拖拽改变元素大小的方法(附demo源码下载)
2016/02/25 Javascript
JS获取和修改元素样式的实例代码
2016/08/06 Javascript
js+css3实现旋转效果
2017/01/20 Javascript
js/jquery控制页面动态加载数据 滑动滚动条自动加载事件的方法
2017/02/08 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
2017/12/15 Javascript
Vue.js结合bootstrap前端实现分页和排序效果
2018/12/29 Javascript
vue spa应用中的路由缓存问题与解决方案
2019/05/31 Javascript
微信小程序scroll-view锚点链接滚动跳转功能
2019/12/12 Javascript
[03:02]2020完美世界城市挑战赛(秋季赛)总决赛回顾
2021/03/11 DOTA
Python实现识别手写数字大纲
2018/01/29 Python
Python实现模拟浏览器请求及会话保持操作示例
2018/07/30 Python
python_array[0][0]与array[0,0]的区别详解
2020/02/18 Python
英国水族馆和池塘用品购物网站:Warehouse Aquatics
2019/08/29 全球购物
化学相关工作求职信
2013/10/02 职场文书
小学教师师德师风个人整改措施
2014/09/18 职场文书
行风评议整改报告
2014/11/06 职场文书
2014年幼儿园工作总结
2014/11/10 职场文书
出国留学单位推荐信
2015/03/26 职场文书
读书笔记格式
2015/07/02 职场文书
党章党规党纪学习心得体会
2016/01/14 职场文书
2016年庆“七一”主题党日活动总结
2016/04/05 职场文书
《思路决定出路》读后感3篇
2019/12/11 职场文书
python3使用diagrams绘制架构图的步骤
2021/04/08 Python