写了那么久SQL,你用过CASE表达式吗?

CASE表达式

CASE表达式不依赖于具体的数据库体术,可以提高代码的可移植性。

  • 简单表达式

    CASE sex 
    	WHEN '1' THEN '男' 
    	WHEN '2' THEN '女'
    ELSE '其他' END
    复制代码
  • 搜索表达式

    CASE WHEN sex = '1' THEN '男' 
    	 WHEN sex = '2' THEN '女'
    ELSE '其他' END	
    复制代码

上面两种写法执行的结果是相同的,如果sex字段是1,结果为男,反之为女。简单表达式虽然与搜索表达式的执行结果是一样的,但是简单表达式能写的条件是有限的,所以一般的时候基本采用搜索表达式来写。

在写SQL的时候需要注意,在发现为真的WHEN子句时,CASE表示式的真假值判断就会终止,剩下的WHEN子句会被忽略,所以使用WHEN子句的时候要注意条件的排他性

注意事项:

  • 分支返回的数据类型要统一

    不能一个返回字符类型一个返回数值类型

  • 不能忽略END不写

  • 学会养成写ELSE子句的习惯

    不写ELSE的时候,执行结果是NULL。但不写可能会造成语法没错误,但是结果不对。

转换新的统计方式

如下数据表,两个字段分别为城市和人数,把同一个省份下的城市对应的人数统计出来:

数据源表:

城市人数表

执行结果:

地区人数

SELECT CASE city
    WHEN '哈尔滨' THEN '黑龙江'
    WHEN '齐齐哈尔' THEN '黑龙江'
    WHEN '佳木斯' THEN '黑龙江'
    WHEN '宝山区' THEN '上海'
    WHEN '黄浦区' THEN '上海'
    ELSE '其他' END AS '地区',
    SUM(population) AS '人数'
FROM city_population
GROUP BY CASE city
     WHEN '哈尔滨' THEN '黑龙江'
     WHEN '齐齐哈尔' THEN '黑龙江'
     WHEN '佳木斯' THEN '黑龙江'
     WHEN '宝山区' THEN '上海'
     WHEN '黄浦区' THEN '上海'
     ELSE '其他' END;
复制代码

其实上面这样写是非常的麻烦的,如果以后修改case中的子句,那么可能会忽略一部分没有修改,所以方便的写法如下:

SELECT CASE city
    WHEN '哈尔滨' THEN '黑龙江'
    WHEN '齐齐哈尔' THEN '黑龙江'
    WHEN '佳木斯' THEN '黑龙江'
    WHEN '宝山区' THEN '上海'
    WHEN '黄浦区' THEN '上海'
    ELSE '其他' END AS 地区,
    SUM(population) AS '人数'
FROM city_population
GROUP BY 地区;
复制代码

其实GROUP BY使用的就是SELECT中定义的别称地区,严格来说这种写法是违规的,违反了SQL标准规则。因为GROUP BY要比SELECT先执行,比如Oracle、DB2等等数据中就不支持这样写,但是MySQL、PostgreSQL中就可以这样写。因为这些数据库在执行查询语句的时候会先对SELECT子句列表进行扫描,对列进行计算。写法虽然简洁,但是不推荐使用,可以移植性差。

一条SQL做不同条件的统计

有一张表名为:city_population_2,每个城市的男性为1,女性为2,也数据源的行结构转换为结果表中的列结构。

数据源表:

统计结果表:

SELECT
	city AS '城市',
	SUM( CASE WHEN sex = 1 THEN population ELSE 0 END ) AS '男',
	SUM( CASE WHEN sex = 2 THEN population ELSE 0 END ) AS '女' 
FROM
	city_population_2 
GROUP BY
	city;
复制代码

在update里面进行条件分支

有一张工资表salaries,按照规定,工资8000(包含8000)以上的员工涨薪500元,工资6000(包含6000)以上不到8000的员工涨薪1000元,其它员工保持不变。

数据源表:

结果表:

UPDATE salaries SET salary = CASE WHEN salary >= 8000 THEN salary + 500 
								  WHEN salary < 8000 AND salary >= 6000 THEN salary + 1000 
								  ELSE salary END;
复制代码