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 相关文章推荐
SqlServer: 如何更改表的文件组?(进而改变存储位置)
Apr 05 SQL Server
SQL SERVER中常用日期函数的具体使用
Apr 08 SQL Server
SQLServer2008提示评估期已过解决方案
Apr 12 SQL Server
SQL 尚未定义空闲 CPU 条件 - OnIdle 作业计划将不起任何作用
Jun 30 SQL Server
sql server删除前1000行数据的方法实例
Aug 30 SQL Server
Spark SQL 2.4.8 操作 Dataframe的两种方式
Oct 16 SQL Server
SQL SERVER存储过程用法详解
Feb 24 SQL Server
详解在SQLPlus中实现上下键翻查历史命令的功能
Mar 18 SQL Server
SQLServer RANK() 排名函数的使用
Mar 23 SQL Server
SQL使用复合索引实现数据库查询的优化
May 25 SQL Server
SQL Server2019安装的详细步骤实战记录(亲测可用)
Jun 10 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
融入意大利的咖啡文化
2021/03/03 咖啡文化
PHP脚本的10个技巧(4)
2006/10/09 PHP
PHP utf-8编码问题,utf8编码,数据库乱码,页面显示输出乱码
2013/04/08 PHP
thinkphp3.x中session方法的用法分析
2016/05/20 PHP
Yii框架分页实现方法详解
2017/05/20 PHP
用javascript getComputedStyle获取和设置style的原理
2008/10/10 Javascript
js对象的比较
2011/02/26 Javascript
使用JavaScript修改浏览器URL地址栏的实现代码
2013/10/21 Javascript
js动态创建标签示例代码
2014/06/09 Javascript
JavaScript中的值类型详细介绍
2014/12/29 Javascript
Javascript基础教程之数组 array
2015/01/18 Javascript
Node.js 学习笔记之简介、安装及配置
2015/03/03 Javascript
pace.js页面加载进度条插件
2015/09/29 Javascript
实例详解AngularJS实现无限级联动菜单
2016/01/15 Javascript
JS中改变this指向的方法(call和apply、bind)
2016/03/26 Javascript
Jquery Easyui验证组件ValidateBox使用详解(20)
2016/12/18 Javascript
Vue.js实现文章评论和回复评论功能
2020/05/30 Javascript
iscroll实现下拉刷新功能
2017/07/18 Javascript
解决layui表格的表头不滚动的问题
2019/09/04 Javascript
vue实现鼠标经过动画
2019/10/16 Javascript
让IDE识别webpack的别名alias的实现方法
2020/05/06 Javascript
Python合并两个字典的常用方法与效率比较
2015/06/17 Python
python中format()函数的简单使用教程
2018/03/14 Python
PyQt5重写QComboBox的鼠标点击事件方法
2019/06/25 Python
纯HTML+CSS3制作导航菜单(附源码)
2013/04/24 HTML / CSS
CSS3实现瀑布流布局与无限加载图片相册的实例代码
2016/12/22 HTML / CSS
HTML5超炫酷粒子效果的进度条的实现示例
2019/08/23 HTML / CSS
BIFFI美国站:意大利BIFFI BOUTIQUES豪华多品牌时装零售公司
2020/02/11 全球购物
自1926年以来就为冰岛保持温暖:66°North
2020/11/27 全球购物
专业毕业生个性的自我评价
2013/10/03 职场文书
大学生毕业求职简历的自我评价
2013/10/24 职场文书
献爱心活动总结
2014/05/07 职场文书
财务会计专业求职信
2014/06/09 职场文书
专题民主生活会对照检查材料思想汇报
2014/09/29 职场文书
十大最帅动漫男主 碓冰拓海上榜,第一是《灌篮高手》男主角
2022/03/18 日漫
《艾尔登法环》Boss腐烂树灵很有可能是《黑暗之魂3》的一个废案
2022/04/11 其他游戏