【SQL基础】case when和decode的用法与区别

一、case when
case when 类似我们的if ...else ,判断语句
语法如下:
CASE expr WHEN expr1 THEN return_expr1
         [WHEN expr2 THEN return_expr2
          ...
          WHEN exprn THEN return_exprn
          ELSE else_expr]
END

第二种延伸用法:
CASE
         WHEN  expr1 THEN return_expr1
         [WHEN expr2 THEN return_expr2
          ....
          WHEN exprn THEN return_exprn
          ELSE else_expr]
END


-- 如果部门编号为10的,显示为dept10
-- 如果部门编号为20的,显示为dept20
-- 如果部门编号为30的,显示为dept30
-- 否则显示为other
-- 这一列查询的结果,列名显示为 department
select ename,sal,case deptno when 10 then 'dept10'
                             when 20 then 'dept20' 
                             when 30 then 'dept30' 
                 else 'other' end department 
from emp ;

ENAME                       SAL DEPARTMENT
-------------------- ---------- -------------
SMITH                       800 dept20
ALLEN                      1600 dept30
WARD                       1250 dept30
JONES                      2975 dept20
MARTIN                     1250 dept30
BLAKE                      2850 dept30
CLARK                      2450 dept10
SCOTT                      3000 dept20
KING                       5000 dept10
TURNER                     1500 dept30
ADAMS                      1100 dept20
JAMES                       950 dept30
FORD                       3000 dept20
MILLER                     1300 dept10


另一种写法:
select ename,sal,case when deptno=10 then 'dept10'
                      when deptno =20 then 'dept20' 
                      when deptno =30 then 'dept30' 
                 else 'other' end department 
from emp;
ENAME                       SAL DEPARTMENT
-------------------- ---------- -------------
SMITH                       800 dept20
ALLEN                      1600 dept30
WARD                       1250 dept30
JONES                      2975 dept20
MARTIN                     1250 dept30
BLAKE                      2850 dept30
CLARK                      2450 dept10
SCOTT                      3000 dept20
KING                       5000 dept10
TURNER                     1500 dept30
ADAMS                      1100 dept20
JAMES                       950 dept30
FORD                       3000 dept20
MILLER                     1300 dept10

这里是等值,结果是一样的。

如果是不等值的或是有多个表达式,就只能用第二种了,比如:
select ename,sal,
       case when deptno= 10 or deptno = 20 or deptno = 30 then 'dept'||deptno end dept
from emp;

select ename,sal,
       case when deptno<=20 then 'dept'||deptno end dept
from emp;

select ename,sal,case when sal>0 and sal<=1500 then 'level1'
                      when sal>1500 and sal<=2500 then 'level2' 
                      when sal>2500 and sal<=4500 then 'level3' 
                      else 'level4' end sal_level
from emp 
order by sal desc;

ENAME                       SAL SAL_LEVEL
-------------------- ---------- -----------
KING                       5000 level4
FORD                       3000 level3
SCOTT                      3000 level3
JONES                      2975 level3
BLAKE                      2850 level3
CLARK                      2450 level2
ALLEN                      1600 level2
TURNER                     1500 level1
MILLER                     1300 level1
WARD                       1250 level1
MARTIN                     1250 level1
ADAMS                      1100 level1
JAMES                       950 level1
SMITH                       800 level1


二、decode
语法:
DECODE(col|expression, search1, result1
                       [, search2, result2,...,]
                        ...
                       [, searchn, resultn,...,]
                       [, default])
如果 条件=值1,那么显示结果1
如果 条件=值2,那么显示结果2
....
如果 条件=值n,那么显示结果n
都不符合,则显示缺省值

--结果和上面用case when一样,但这句看起来简洁得多了
select ename,sal,
       decode(deptno,10,'dept10',20,'dept20',30,'dept30','other') department  
from emp;
ENAME                       SAL DEPARTMENT
-------------------- ---------- ------------
SMITH                       800 dept20
ALLEN                      1600 dept30
WARD                       1250 dept30
JONES                      2975 dept20
MARTIN                     1250 dept30
BLAKE                      2850 dept30
CLARK                      2450 dept10
SCOTT                      3000 dept20
KING                       5000 dept10
TURNER                     1500 dept30
ADAMS                      1100 dept20
JAMES                       950 dept30
FORD                       3000 dept20
MILLER                     1300 dept10


延伸用法:与sign函数联用比较大小
注:sign()函数根据参数1的值是0、正数还是负数,分别返回0、1、-1
select ename,sal,decode(sign(sal-2000),1, '>2000 ',-1, '<2000 ', '=2000 ') sal_level
from emp;
ENAME                       SAL SAL_LEVEL
-------------------- ---------- -----------
SMITH                       800 <2000
ALLEN                      1600 <2000
WARD                       1250 <2000
JONES                      2975 >2000
MARTIN                     1250 <2000
BLAKE                      2850 >2000
CLARK                      2450 >2000
SCOTT                      3000 >2000
KING                       5000 >2000
TURNER                     1500 <2000
ADAMS                      1100 <2000
JAMES                       950 <2000
FORD                       3000 >2000
MILLER                     1300 <2000

三、DECODE 与CASE WHEN 的比较
      1.DECODE 只有Oracle 才有,其它数据库不支持;
      2.CASE WHEN的用法, Oracle、SQL Server、 MySQL 都支持;
      3.DECODE 只能用做相等判断,但是可以配合sign函数进行大于,小于,等于的判断,CASE when可用于=,>=,<,<=,<>,is null,is not null 等的判断;
      4.DECODE 使用其来比较简洁,CASE 虽然复杂但更为灵活;
      5.另外,在decode中,null和null是相等的,但在case when中,只能用is null来判断,示例如下:

      emp表中有一列comm,如果这列为null,则显示为0,否则,显示为原值:
--decode可以显示我们要求的结果
SQL> select ename,decode(comm,null,0,comm) comma from emp;

ENAME                     COMMA
-------------------- ----------
SMITH                         0
ALLEN                       300
WARD                        500
JONES                         0
MARTIN                     1400
BLAKE                         0
CLARK                         0
SCOTT                         0
KING                          0
TURNER                        0
ADAMS                         0
JAMES                         0
FORD                          0
MILLER                        0

-- null没有转成0,仍然是null,不是我们要求的结果
SQL> select ename,(case comm when null then 0 else comm end) comm from emp;

ENAME                      COMM
-------------------- ----------
SMITH
ALLEN                       300
WARD                        500
JONES
MARTIN                     1400
BLAKE
CLARK
SCOTT
KING
TURNER                        0
ADAMS
JAMES
FORD
MILLER

--这样才可以成功将null显示为0
SQL> select ename,(case when comm is null then 0 else comm end) comm from emp;

ENAME                      COMM
-------------------- ----------
SMITH                         0
ALLEN                       300
WARD                        500
JONES                         0
MARTIN                     1400
BLAKE                         0
CLARK                         0
SCOTT                         0
KING                          0
TURNER                        0
ADAMS                         0
JAMES                         0
FORD                          0
MILLER                        0

你可能感兴趣的:(Oracle常见问题)