SQL CASE WHEN 用法的深度解析
备注:本文更新于2020年6月18日
前言
本文是对 SQL CASE WHEN 用法的深度解析,重新理解case when then else end用法。
在SQL的世界中CASE WHEN语句相当于if-else语句。虽然看似简单,但是CASE WHEN并不容易掌握,CASE的用法分为两种形式:简单CASE函数和CASE条件表达式函数。简单CASE函数,类似如下形式:
CASE SCORE WHEN 'A' THEN '优' ELSE '不及格' END
其中,SCORE更像是CASE函数的参数,因为只能传递一个参数,所以CASE的这种用法并不灵活。简单CASE函数只能应对一些简单的业务场景,而CASE条件表达式函数的用法则更加灵活。见下面的应用场景:
CASE SCORE WHEN 'A' THEN '优' ELSE '不及格' END
CASE SCORE WHEN 'B' THEN '良' ELSE '不及格' END
CASE SCORE WHEN 'C' THEN '中' ELSE '不及格' END
等同于,使用CASE条件表达式函数实现:
CASE WHEN SCORE = 'A' THEN '优'
WHEN SCORE = 'B' THEN '良'
WHEN SCORE = 'C' THEN '中'
ELSE '不及格'
END
需要注意的是:THEN后边的值与ELSE后边的值类型应一致,否则会报错。如下:
CASE SCORE WHEN 'A' THEN '优' ELSE 0 END
'优'和0数据类型不一致则报错:
[Err] ORA-00932: 数据类型不一致: 应为 CHAR, 但却获得 NUMBER
1、CASE函数和CASE表达式函数本质都是代码块,具有返回值
在SQL中CASE函数和CASE表达式函数本质都是代码块,常用被括号括起来,如下所示:
SELECT
s.s_id,
s.s_name,
s.s_sex,
(CASE
WHEN s.s_sex = '1' THEN '男'
WHEN s.s_sex = '2' THEN '女'
ELSE '其他'
END) as sex,
s.s_age,
s.class_id
FROM
t_b_student s
CASE 的常用格式是:case when then else end,这是一种表达式,在编程语言中,任何表达式都是有返回值的,SQL也不例外,可用于update更新语句,如下场景所示:现在某公司员人工资信息表如下:
name | salary |
小明 | 10500 |
小红 | 8000 |
小李 | 5000 |
现在公司出台了一个奇葩的规定:
(1)对当前工资为 1 万以上的员工,降薪 10%。
(2)对当前工资低于 1 万的员工,加薪 20%。
一些人不假思索可能写出了以下的 SQL:
--条件1
UPDATE Salaries
SET salary = salary * 0.9 WHERE salary >= 10000;
--条件2
UPDATE Salaries
SET salary = salary * 1.2 WHERE salary < 10000;
这么做其实是有问题的。对小明来说,他的工资是 10500,执行第一个 SQL 后,工资变为 10500 x 0.9 = 9450,紧接着又执行条件 2,工资变为了 9450 x 1.2 = 11340,反而涨薪了!
如果用 CASE WHEN 可以解决此类问题,如下所示:
UPDATE
Salaries
SET
salary = CASE
WHEN salary >= 10000 THEN salary * 0.9
WHEN salary < 10000 THEN salary * 1.2
ELSE salary
END;
2、CASE用法1:CASE函数
CASE函数的语法如下:
CASE expression
WHEN value1 THEN returnvalue1
WHEN value2 THEN returnvalue2
WHEN value3 THEN returnvalue3
ELSE defaultreturnvalue
END
CASE函数对表达式expression进行测试,如果 expression 等于value1 则返回 returnvalue1;如果 expression 等于value2 则返回 returnvalue2,如果 expression 等于 value3 则返回 returnvalue3....以此类推,如果不符合所有的WHEN条件,则返回默认值 defaultreturnvalue。
CASE函数和普通编程语言中的 SWITCH-CASE 语句非常类似。使用CASE函数可以实现非常复杂的业务逻辑。如下所示:
select name,
(
case name
when 'tom' then 'A'
when 'adam' then 'B'
else 'C'
end
) as level
from `t_employee`
3、CASE用法2:CASE条件表达式函数
上中介绍的CASE函数的用法只能用来实现简单的“等于”逻辑。如果要实现“如果年龄小于18则返回未成年人,否则返回成年人”的功能是不可能的。值得庆幸的是,CASE还提供了第二种用法,其语法如下:
CASE
WHEN condition1 THEN returnvalue1
WHEN condition2 THEN returnvalue2
WHEN condition3 THEN returnvalue3
ELSE defaultreturnvalue
END
其中的condition1、condition 2、condition3为条件表达式,CASE 对这个表达式从前向后进行测试,如果条件 condition1 为真则返回 returnvalue1,否则如果条件 condition2 为真则返回 returnvalue2,否则如果条件 condition3 为真则返回returnvalue3。以此类推,如果不符合所有的 WHEN 条件,则返回默认值。
select name,
(
case
when salary < 5000 then 'low'
when salary <= 8000 then 'middle'
else 'heigh'
end
) as salary
from `t_employee`
4、Java中case用法
switch case 语句语法格式如下:
switch(expression)
{
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}
public class Test
{
public static void main(String args[])
{
char grade = 'A';
switch (grade)
{
case 'A':
System.out.println("优秀");
break;
case 'B':
case 'C':
System.out.println("良好");
break;
case 'D':
System.out.println("及格");
break;
case 'F':
System.out.println("你需要再努力努力");
break;
default:
System.out.println("未知等级");
}
System.out.println("你的等级是 " + grade);
}
}
5、如何记住SQL中的CASE的语法格式
在SQL中CASE的用处,人人都能说出一二三来,在Java中case的用法,同样的人人皆知。但是在SQL中,能熟练的使用CASE,往往人不多了。究其原因,在于CASE的语法格式很多人没有记住。可以结合Java中case的用法来记忆:
第一:SQL中的 CASE expression,相当于 Java 中的 switch(expression)
第二:SQL中的 WHEN value1 THEN returnvalue1,相当于 Java 中的 case value : statement
第三:SQL中的 ELSE defaultreturnvalue,相当于 Java 中的 default : statement