- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章sql中case语句的用法浅谈由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
SQL中Case的使用方法 。
Case具有两种格式。简单Case函数和Case搜索函数.
--简单Case函数 。
。
CASE sex 。
WHEN '1' THEN '男' 。
WHEN '2' THEN '女' 。
ELSE '其他' END 。
--Case搜索函数 。
CASE WHEN sex = '1' THEN '男' 。
WHEN sex = '2' THEN '女' 。
ELSE '其他' END 。
这两种方式,可以实现相同的功能。简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式.
。
还有一个需要注意的问题,Case函数只返回第一个符合条件的值,剩下的Case部分将会被自动忽略.
--比如说,下面这段SQL,你永远无法得到“第二类”这个结果 。
CASE WHEN col_1 IN ( 'a', 'b') THEN '第一类' 。
。
WHEN col_1 IN ('a') THEN '第二类' 。
ELSE'其他' END 。
下面我们来看一下,使用Case函数都能做些什么事情.
。
一,已知数据按照另外一种方式进行分组,分析.
有如下数据:(为了看得更清楚,我并没有使用国家代码,而是直接用国家名作为Primary Key) 。
国家(country)人口(population) 。
中国600 。
美国100 。
加拿大100 。
英国200 。
法国300 。
日本250 。
德国200 。
墨西哥50 。
印度250 。
根据这个国家人口数据,统计亚洲和北美洲的人口数量。应该得到下面这个结果.
洲人口 。
亚洲1100 。
北美洲250 。
其他700 。
想要解决这个问题,你会怎么做?生成一个带有洲Code的View,是一个解决方法,但是这样很难动态的改变统计的方式.
如果使用Case函数,SQL代码如下
SELECT SUM(population).
。
CASE country 。
WHEN '中国' THEN '亚洲' 。
WHEN '印度' THEN '亚洲' 。
WHEN '日本' THEN '亚洲' 。
WHEN '美国' THEN '北美洲' 。
WHEN '加拿大' THEN '北美洲' 。
WHEN '墨西哥' THEN '北美洲' 。
ELSE '其他' END 。
FROM Table_A 。
GROUP BY CASE country 。
WHEN '中国' THEN '亚洲' 。
WHEN '印度' THEN '亚洲' 。
WHEN '日本' THEN '亚洲' 。
WHEN '美国' THEN '北美洲' 。
WHEN '加拿大' THEN '北美洲' 。
WHEN '墨西哥' THEN '北美洲' 。
ELSE '其他' END,
同样的,我们也可以用这个方法来判断工资的等级,并统计每一等级的人数。SQL代码如下; 。
SELECT 。
。
CASE WHEN salary <= 500 THEN '1' 。
WHEN salary > 500 AND salary <= 600 THEN '2' 。
WHEN salary > 600 AND salary <= 800 THEN '3' 。
WHEN salary > 800 AND salary <= 1000 THEN '4' 。
ELSE NULL END salary_class.
COUNT(*) 。
FROM Table_A 。
GROUP BY 。
CASE WHEN salary <= 500 THEN '1' 。
WHEN salary > 500 AND salary <= 600 THEN '2' 。
WHEN salary > 600 AND salary <= 800 THEN '3' 。
WHEN salary > 800 AND salary <= 1000 THEN '4' 。
ELSE NULL END,
。
二,用一个SQL语句完成不同条件的分组.
有如下数据 。
国家(country)性别(sex)人口(population) 。
中国1 340 。
中国2 260 。
美国1 45 。
美国2 55 。
加拿大1 51 。
加拿大2 49 。
英国1 40 。
英国2 60 。
按照国家和性别进行分组,得出结果如下 。
国家男女 。
中国340 260 。
美国45 55 。
加拿大51 49 。
英国40 60 。
普通情况下,用UNION也可以实现用一条语句进行查询。但是那样增加消耗(两个Select部分),而且SQL语句会比较长.
下面是一个是用Case函数来完成这个功能的例子 。
SELECT country.
。
SUM( CASE WHEN sex = '1' THEN 。
population ELSE 0 END), --男性人口 。
SUM( CASE WHEN sex = '2' THEN 。
population ELSE 0 END) --女性人口 。
FROM Table_A 。
GROUP BY country,
这样我们使用Select,完成对二维表的输出形式,充分显示了Case函数的强大.
。
三,在Check中使用Case函数.
在Check中使用Case函数在很多情况下都是非常不错的解决方法。可能有很多人根本就不用Check,那么我建议你在看过下面的例子之后也尝试一下在SQL中使用Check.
下面我们来举个例子 。
公司A,这个公司有个规定,女职员的工资必须高于块。如果用Check和Case来表现的话,如下所示 。
CONSTRAINT check_salary CHECK 。
。
( CASE WHEN sex = '2' 。
THEN CASE WHEN salary > 1000 。
THEN 1 ELSE 0 END 。
ELSE 1 END = 1 ) 。
。
如果单纯使用Check,如下所示 。
CONSTRAINT check_salary CHECK 。
。
( sex = '2' AND salary > 1000 ) 。
女职员的条件倒是符合了,男职员就无法输入了.
。
四,根据条件有选择的UPDATE.
例,有如下更新条件 。
工资以上的职员,工资减少% 。
工资在到之间的职员,工资增加% 。
很容易考虑的是选择执行两次UPDATE语句,如下所示 。
--条件 。
。
UPDATE Personnel 。
SET salary = salary * 0.9 。
WHERE salary >= 5000,
--条件 。
UPDATE Personnel 。
SET salary = salary * 1.15 。
WHERE salary >= 2000 AND salary < 4600,
但是事情没有想象得那么简单,假设有个人工资块。首先,按照条件,工资减少%,变成工资。接下来运行第二个SQL时候,因为这个人的工资是在到的范围之内,需增加%,最后这个人的工资结果是,不但没有减少,反而增加了。如果要是反过来执行,那么工资的人相反会变成减少工资。暂且不管这个规章是多么荒诞,如果想要一个SQL 语句实现这个功能的话,我们需要用到Case函数。代码如下
UPDATE Personnel 。
。
SET salary = CASE WHEN salary >= 5000 。
THEN salary * 0.9 。
WHEN salary >= 2000 AND salary < 4600 。
THEN salary * 1.15 。
ELSE salary END,
。
这里要注意一点,最后一行的ELSE salary是必需的,要是没有这行,不符合这两个条件的人的工资将会被写成NUll,那可就大事不妙了。在Case函数中Else部分的默认值是NULL,这点是需要注意的地方.
这种方法还可以在很多地方使用,比如说变更主键这种累活.
一般情况下,要想把两条数据的Primary key,a和b交换,需要经过临时存储,拷贝,读回数据的三个过程,要是使用Case函数的话,一切都变得简单多了.
p_key col_1 col_2 。
a 1 张三 。
b 2 李四 。
c 3 王五 。
假设有如上数据,需要把主键a和b相互交换。用Case函数来实现的话,代码如下 。
UPDATE SomeTable 。
。
SET p_key = CASE WHEN p_key = 'a' 。
THEN 'b' 。
WHEN p_key = 'b' 。
THEN 'a' 。
ELSE p_key END 。
WHERE p_key IN ('a', 'b'),
。
同样的也可以交换两个Unique key。需要注意的是,如果有需要交换主键的情况发生,多半是当初对这个表的设计进行得不够到位,建议检查表的设计是否妥当.
五,两个表数据是否一致的检查.
Case函数不同于DECODE函数。在Case函数中,可以使用BETWEEN,LIKE,IS NULL,IN,EXISTS等等。比如说使用IN,EXISTS,可以进行子查询,从而实现更多的功能.
下面具个例子来说明,有两个表,tbl_A,tbl_B,两个表中都有keyCol列。现在我们对两个表进行比较,tbl_A中的keyCol列的数据如果在tbl_B的keyCol列的数据中可以找到,返回结果'Matched',如果没有找到,返回结果'Unmatched'.
要实现下面这个功能,可以使用下面两条语句 。
--使用IN的时候 。
。
SELECT keyCol.
CASE WHEN keyCol IN ( SELECT keyCol FROM tbl_B ) 。
THEN 'Matched' 。
ELSE 'Unmatched' END Label 。
FROM tbl_A,
--使用EXISTS的时候 。
SELECT keyCol.
CASE WHEN EXISTS ( SELECT * FROM tbl_B 。
WHERE tbl_A.keyCol = tbl_B.keyCol ) 。
THEN 'Matched' 。
ELSE 'Unmatched' END Label 。
FROM tbl_A,
。
使用IN和EXISTS的结果是相同的。也可以使用NOT IN和NOT EXISTS,但是这个时候要注意NULL的情况.
六,在Case函数中使用合计函数 。
假设有下面一个表 。
学号(std_id) 课程ID(class_id) 课程名(class_name) 主修flag(main_class_flg) 。
100 1 经济学Y 。
100 2 历史学N 。
200 2 历史学N 。
200 3 考古学Y 。
200 4 计算机N 。
300 4 计算机N 。
400 5 化学N 。
500 6 数学N 。
有的学生选择了同时修几门课程(100,200)也有的学生只选择了一门课程(300,400,500)。选修多门课程的学生,要选择一门课程作为主修,主修flag里面写入Y。只选择一门课程的学生,主修flag为N(实际上要是写入Y的话,就没有下面的麻烦事了,为了举例子,还请多多包含).
现在我们要按照下面两个条件对这个表进行查询 。
只选修一门课程的人,返回那门课程的ID 。
选修多门课程的人,返回所选的主课程ID 。
简单的想法就是,执行两条不同的SQL语句进行查询.
条件 。
--条件:只选择了一门课程的学生 。
。
SELECT std_id, MAX(class_id) AS main_class 。
FROM Studentclass 。
GROUP BY std_id 。
HAVING COUNT(*) = 1,
。
执行结果 。
STD_ID MAIN_class 。
------ ---------- 。
300 4 。
400 5 。
500 6 。
条件 。
--条件:选择多门课程的学生 。
。
SELECT std_id, class_id AS main_class 。
FROM Studentclass 。
WHERE main_class_flg = 'Y' ,
。
执行结果 。
STD_ID MAIN_class 。
------ ---------- 。
100 1 。
200 3 。
如果使用Case函数,我们只要一条SQL语句就可以解决问题,具体如下所示 。
SELECT std_id.
。
CASE WHEN COUNT(*) = 1 --只选择一门课程的学生的情况 。
THEN MAX(class_id) 。
ELSE MAX(CASE WHEN main_class_flg = 'Y' 。
THEN class_id 。
ELSE NULL END 。
) 。
END AS main_class 。
FROM Studentclass 。
GROUP BY std_id,
。
运行结果 。
STD_ID MAIN_class 。
------ ---------- 。
100 1 。
200 3 。
300 4 。
400 5 。
500 6 。
通过在Case函数中嵌套Case函数,在合计函数中使用Case函数等方法,我们可以轻松的解决这个问题。使用Case函数给我们带来了更大的自由度.
最后提醒一下使用Case函数的新手注意不要犯下面的错误 。
CASE col_1 。
。
WHEN 1 THEN 'Right' 。
WHEN NULL THEN 'Wrong' 。
END 。
在这个语句中When Null这一行总是返回unknown,所以永远不会出现Wrong的情况。因为这句可以替换成WHEN col_1 = NULL,这是一个错误的用法,这个时候我们应该选择用WHEN col_1 IS NULL.
最后此篇关于sql中case语句的用法浅谈的文章就讲到这里了,如果你想了解更多关于sql中case语句的用法浅谈的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
最近我在用 RestSharp消耗我的 Restful 资源。并期望在服务器和客户端之间与 JSon 交换数据。下面是我的 C# 代码。 var client = new RestSharp.Rest
我正在阅读 Bartosz Milewski 的一篇文章,其中他定义了以下函数: instance Applicative Chan where pure x = Chan (repeat x)
‘…' 其实是go的一种语法糖。 它的第一个用法主要是用于函数有多个不定参数的情况,可以接受多个不确定数量的参数。 第二个用法是slice可以被打散进行传递。 实例:
前言 在算face_track_id map有感: 开始验证 data={"state":[1,1,2,2,1,2,2,2],"pop":[&quo
本文实例讲述了php访问数组最后一个元素的函数end()用法。分享给大家供大家参考。具体分析如下: end()函数在PHP中用于检索数组中的最后一个元素。end()函数需要一个数组作为其唯一参数,
我使用的是 jdk1.8.0_92。我的虚拟机如下所示。 $java -version java version "1.8.0_92" Java(TM) SE Runtime Environment
我的情况是我需要将所有匹配 http://mywebsite.com/portfolio/[anyname] 的请求定向到 http://mywebsite.com/portfolio.php?用户名
我正在尝试在 NLTK 中使用语音标记并使用了以下命令: >>> text = nltk.word_tokenize("And now for something completely differe
#include typedef QList IntList; qRegisterMetaType("IntList"); error C2909: 'qRegisterMetaType':
来自 here我知道 BN_CTX 是一个保存 BIGNUM 临时变量的结构。这些 BIGNUM 变量什么时候会进入 BN_CTX 的 BN_POOL?如果我有一个 bignum_ctx BN_CTX
尝试为 ABPersonRef 创建对象例子:ABpersonRef 引用; 已包含Addressbook和AddressBookUI框架即使这样,当我编译时,它仍显示“ABPersonRef”未声明
我无法使用 GetAltTabInfo。可能是一个愚蠢的错误,但这有什么问题呢? HWND taskSwitcher = FindWindow(L"TaskSwitcherWnd", L"Task S
JSLint4Java 是 JSLint 的 Java 包装器。我需要这样的东西在我的 GWT 项目中使用,但使用 JSLint4Java 的唯一方法似乎是从命令行或通过 ANT 任务。有谁知道是否有
我有一个持久化实体对象的方法 persistData() 。我有另一个方法 findData() ,它对同一实体类执行 find() 操作以获取持久的主键值。当我在实体类的@PostPersist中调
下面是我的代码。请查看。 1. bool isUnavailable = db.Deploys.Where(p => p.HostEnvironmentId == Guid.Parse(h
这个问题已经有答案了: Why can't a Generic Type Parameter have a lower bound in Java? (6 个回答) 已关闭 9 年前。 我试图理解为什
我正在尝试使用 scala 编译器 Y 警告,但我认为我做得不对。在下面的示例中,nums 未使用,因此我希望 -Ywarn-value-discard 打印一个警告。有两个 if 条件,一个嵌套在另
用户被要求从某个给定的集合中选择一个 ID。我检查该 ID 是否存在于我的集合中,如果不存在,我会抛出 IndexOutOfBoundsException 并稍后捕获它。我实际上可以使用该异常来达到这
我正在尝试减少从 OSM 路径数据生成的形状文件。我正在使用 VTS 的 DouglasPeuckerSimplifier 实现。我想为特定 GTFS(通用交通提要规范)构建路线图的 geojson。
我明白了?!是排除某个模式,例如 a(?!b) 表示如果“a”后面没有“b”,它将匹配“a”。我的问题是,假设我有一个包含以下内容的文件: a cat is a cat, a dog is a dog
我是一名优秀的程序员,十分优秀!