MySQL 中的 DECODE 函数的实现

本贴最后更新于 1323 天前,其中的信息可能已经时移俗易

在 Oracle 中的 decode() 函数

语法如下:

DECODE (expr, search1, result1[, search2, result2…][, default])
它用于比较参数 expr 的值,如果匹配到哪一个 search 条件,就返回对应的 result 结果,可以有多组 search 和 result 的对应关系,如果任何一个 search 条件都没有匹配到,则返回最后 default 的值。default 参数是可选的,如果没有提供 default 参数值,当没有匹配到时,将返回 NULL。

例:
查询职员表,根据职员的职位计算奖励金额,当职位分别是’MANAGER’、’ANALYST’、’SALESMAN’时,奖励金额分别是薪水的 1.2 倍、1.1 倍、1.05 倍,如果不是这三个职位,则奖励金额取薪水值:

SELECT ename, job, sal,
DECODE(job, 'MANAGER', sal * 1.2,
               'ANALYST', sal * 1.1,
              'SALESMAN', sal * 1.05,
sal
     ) bonus
FROM emp;

和 DECODE 函数功能相似的有 CASE 语句,实现类似于 if-else 的操作。

SELECT
    ename,
    job,
    sal,
CASE
    job 
    WHEN 'MANAGER' THEN
    sal * 1.2 
    WHEN 'ANALYST' THEN
    sal * 1.1 
    WHEN 'SALESMAN' THEN
    sal * 1.05 ELSE sal 
    END bonus 
FROM
    emp;

DECODE 函数在分组查询中的应用

DECODE 函数可以按字段内容分组,例如:计算职位的人数,analyst/manager 职位属于 vip,其余是普通员工 operation,这种功能无法用 GROUP BY 简单实现。用 decode 的实现方式:

SELECT DECODE(job, 'ANALYST', 'VIP', 
                       'MANAGER', 'VIP', 
                       'OPERATION') job,
COUNT(1) job_cnt
FROM emp
GROUP BY DECODE(job, 'ANALYST', 'VIP', 'MANAGER', 'VIP', 'OPERATION');

DECODE 函数也可以按字段内容排序,例如:Dept 表中按”研发部”、“市场部”、“销售部”排序,用普通的 select 语句,无法按照字面数据排序:

SELECT deptno, dname, loc
FROM dept
ORDER BY 
      DECODE(dname, '研发部',1,'市场部',2,'销售部',3), loc;

MySQL 中实现

在 MySQL 中可以使用 if() 函数完成需要使用 DECODE() 函数的简单情景,复杂一点的可以使用 CASE() 函数。

case 函数和代码里面 if...else...很是相似,个人感觉这就是一个判断选择函数。

语法:

case...when...then...else...end
在这个语法基础上面有书写两种格式:简单 case 函数和 case 搜索函数。
另外有一点,case 函数和 if 函数一样,只要一个判断满足了,后面剩下的 case 部分将会被自动忽略,不再匹配。所以写表达式的时候要特别注意一下。

-- 计算职位的人数,其中,“ANALYST”和“MANAGER”职位用“VIP”表示,其余是普通员工,职位用“OPERATION”显示。分别计算 VIP 职位和普通职员职位的人数

SELECT * FROM emp ORDER BY job;
SELECT empno, ename, IF((job IN ('ANALYST','MANAGER')), 'VIP', 'OPERATION') JOB FROM emp;
SELECT IF((job IN ('ANALYST','MANAGER')), 'VIP', 'OPERATION') JOB, COUNT(1) JOB_COUNT  FROM emp GROUP BY IF((job IN ('ANALYST','MANAGER')), 'VIP', 'OPERATION');
SELECT CASE job WHEN 'ANALYST' THEN 'VIP' WHEN 'MANAGER' THEN 'VIP' ELSE 'OPERATION' END AS JOB, COUNT(1) JOB_COUNT FROM emp GROUP BY CASE job WHEN 'ANALYST' THEN 'VIP' WHEN 'MANAGER' THEN 'VIP' ELSE 'OPERATION' END;
SELECT empno, ename, CASE job WHEN 'ANALYST' THEN 'VIP' WHEN 'MANAGER' THEN 'VIP' ELSE 'OPERATION' END AS JOB FROM emp;
SELECT empno, ename, CASE WHEN job IN ('ANALYST','MANAGER') THEN 'VIP' ELSE 'OPERATION' END AS JOB FROM emp;
SELECT CASE WHEN job IN ('ANALYST', 'MANAGER') THEN 'VIP' ELSE 'OPERATION' END AS JOB, COUNT(*) AS JOB_COUNT FROM emp GROUP BY CASE WHEN job IN ('ANALYST', 'MANAGER') THEN 'VIP' ELSE 'OPERATION' END; -- 不能忘记 END,否则会报错

case 函数还可以与一些统计函数连用。

SELECT 
    SUM(CASE sex WHEN 1 THEN 1 ELSE 0 END ) AS '男生',
    SUM(CASE sex WHEN 0 THEN 1 ELSE 0 END ) AS '女生',
    SUM(CASE WHEN sex=1 OR sex=0 THEN 0 ELSE 1 END) AS '未知'
FROM 
    'tb_student';

结果:

男生 女生 未知
2 2 1

之前的示例使用 SUM() 统计的 SQL 写法。

SELECT 
    SUM(CASE WHEN job IN ('ANALYST','MANAGER') THEN 1 ELSE 0 END) AS VIP, 
    SUM(CASE WHEN job NOT IN ('ANALYST','MANAGER') THEN 1 ELSE 0 END ) AS OPERATION 
FROM emp;

case 在排序子句中的使用

-- 将dept 表中的数据按‘OPERATIONS’、‘ACCOUNTING’、‘SALES’ 进行自定义排序
SELECT deptno, dname, loc FROM dept ORDER BY DECODE(dname, 'OPERATIONS', 1, 'ACCOUNTING', 2, 'SALES', 3); -- Oracle 中用法
SELECT deptno, dname, loc FROM dept ORDER BY CASE dname WHEN 'OPERATIONS' THEN 1 WHEN 'ACCOUNTING' THEN 2 WHEN 'SALES' THEN 3 END ;

参考:MySQL 函数之 CASE
Mysql——case 函数

  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    330 引用 • 614 回帖 • 2 关注
  • SQL
    124 引用 • 296 回帖 • 3 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    675 引用 • 535 回帖
  • 笔记

    好记性不如烂笔头。

    303 引用 • 777 回帖
1 操作
PeterChu 在 2020-09-05 02:18:08 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...