1.变换结果集成一行1.1. 结果集

DEPTNO        CNT------ ----------    10          3    20          5    30          6

1.2.结果集

DEPTNO_10  DEPTNO_20  DEPTNO_30--------- ---------- ----------        3          5          6

1.3.sql

select sum(case when deptno=10 then 1 else 0 end) as deptno_10,        sum(case when deptno=20 then 1 else 0 end) as deptno_20,        sum(case when deptno=30 then 1 else 0 end) as deptno_30 from emp

1.3.1.对于每一行的原始数据,使用CASE表达式把行变换成列1.4.sql

select max(case when deptno=10 then empcount else null end) as deptno_10,       max(case when deptno=20 then empcount else null end) as deptno_20,       max(case when deptno=30 then empcount else null end) as deptno_30  from (select deptno, count(*) as empcount  from emp group by deptno       ) x

1.4.1.用内嵌视图生成每个部门的员工总人数1.4.2.主查询里的CASE表达式把行转换成列1.4.3.调用MAX函数把几列合并为一行2.反向变换结果集2.1.结果集

DEPTNO_10  DEPTNO_20  DEPTNO_30--------- ---------- ----------        3          5          6

2.2.结果集

DEPTNO        CNT------ ----------    10          3    20          5    30          6

2.3.sql

select dept.deptno,         case dept.deptno              when 10 then emp_cnts.deptno_10              when 20 then emp_cnts.deptno_20              when 30 then emp_cnts.deptno_30         end as CNT    from (  select sum(case when deptno=10 then 1 else 0 end) as deptno_10,         sum(case when deptno=20 then 1 else 0 end) as deptno_20,         sum(case when deptno=30 then 1 else 0 end) as deptno_30    from emp         ) emp_cnts,         (select deptno from dept where deptno <= 30) dept

3.变换结果集成多行3.1.结果集

JOB       ENAME--------- ----------ANALYST   SCOTTANALYST   FORDCLERK     SMITHCLERK     ADAMSCLERK     MILLERCLERK     JAMESMANAGER   JONESMANAGER   CLARKMANAGER   BLAKEPRESIDENT KINGSALESMAN  ALLENSALESMAN  MARTINSALESMAN  TURNERSALESMAN  WARD

3.2.结果集

CLERKS ANALYSTS MGRS  PREZ    SALES------ -------- ----- ---- ------ ---------------MILLER   FORD    CLARK      KING    TURNERJAMES    SCOTT   BLAKE              MARTINADAMS            JONES           WARDSMITH                               ALLEN

3.3.DB23.4.Oracle3.5.SQL Server3.6.使用窗口函数ROW_NUMBER OVER确保每一个JOB/ENAME组合都是唯一的

select max(case when job='CLERK'                  then ename else null end) as clerks,         max(case when job='ANALYST'                  then ename else null end) as analysts,         max(case when job='MANAGER'                  then ename else null end) as mgrs,         max(case when job='PRESIDENT'                  then ename else null end) as prez,         max(case when job='SALESMAN'                  then ename else null end) as sales    from (  select job,         ename,         row_number()over(partition by job order by ename) rn    from emp         ) x   group by rn

3.6.1.1.为了剔除掉Null,需要调用聚合函数MAX,并基于RN执行GROUP BY3.7.PostgreSQL3.8.MySQL3.9.sql

select max(case when job='CLERK'                  then ename else null end) as clerks,         max(case when job='ANALYST'                  then ename else null end) as analysts,         max(case when job='MANAGER'                  then ename else null end) as mgrs,         max(case when job='PRESIDENT'                  then ename else null end) as prez,         max(case when job='SALESMAN'                  then ename else null end) as sales    from (  select e.job,         e.ename,         (select count(*) from emp d           where e.job=d.job and e.empno < d.empno) as rnk    from emp e         ) x   group by rnk

3.9.1.1.使用标量子查询基于EMPNO为每个员工排序3.9.1.2.针对标量子查询的返回值执行GROUP BY3.9.1.3.使用CASE表达式和聚合函数MAX实现结果集变换4.反向变换结果集成一列4.1.把一个查询结果合并成一列4.1.1.希望返回DEPTNO等于10的全体员工的ENAME、JOB和SAL,并且想把3列值合并成1列4.2.DB24.3.Oracle4.4.SQL Server4.5.使用窗口函数ROW_NUMBER OVER

select case rn              when 1 then ename              when 2 then job              when 3 then cast(sal as char(4))         end emps    from (  select e.ename,e.job,e.sal,         row_number()over(partition by e.empno                              order by e.empno) rn    from emp e,         (select *            from emp where job='CLERK') four_rows   where e.deptno=10         ) x

5.删除重复数据5.1.结果集

DEPTNO ENAME------ ---------    10 CLARK       KING       MILLER    20 SMITH       ADAMS       FORD       SCOTT       JONES    30 ALLEN       BLAKE       MARTIN       JAMES       TURNER       WARD

5.1.1.每个DEPTNO只显示一次5.2.DB25.3.SQL Server5.4.使用窗口函数MIN OVER

select case when empno=min_empno              then deptno else null         end deptno,         ename    from (  select deptno,         min(empno)over(partition by deptno) min_empno,         empno,         ename    from emp         ) x

5.5.Oracle

select to_number(           decode(lag(deptno)over(order by deptno),                 deptno,null,deptno)        ) deptno, ename   from emp

6.变换结果集以实现跨行计算

select deptno, sum(sal) as sal  from emp group by deptnoDEPTNO        SAL------ ----------    10       8750    20      10875    30       9400

6.2.算出上述DEPTNO 20和DEPTNO 10之间的工资总额的差值,以及上述DEPTNO 20和DEPTNO 30之间的工资总额差值

select d20_sal - d10_sal as d20_10_diff, d20_sal - d30_sal as d20_30_diff from ( select sum(case when deptno=10 then sal end) as d10_sal, sum(case when deptno=20 then sal end) as d20_sal, sum(case when deptno=30 then sal end) as d30_sal from emp ) totals_by_dept