

SQL> SELECT d.dname, to_char(e.hiredate, 'yyyy') hireyear, COUNT(1)2 FROM emp e, dept d3 WHERE d.deptno = e.deptno4 GROUP BY d.dname, to_char(e.hiredate, 'yyyy');DNAME HIREYEAR COUNT(1)-------------- -------- ----------RESEARCH 1983 1RESEARCH 1981 2SALES 1981 6RESEARCH 1982 1ACCOUNTING 1981 2ACCOUNTING 1982 1RESEARCH 1980 17 rows selected
老板看后非常开心,然后因为我没有把数据按照部门和年份两个维度整理成报表扣了我半个月奖金

SQL> SELECT dname2 ,SUM(decode(hireyear, 1980, cnt)) cnt_803 ,SUM(decode(hireyear, 1981, cnt)) cnt_814 ,SUM(decode(hireyear, 1982, cnt)) cnt_825 ,SUM(decode(hireyear, 1983, cnt)) cnt_836 FROM (SELECT d.dname, to_char(e.hiredate, 'yyyy') hireyear, COUNT(1) cnt7 FROM emp e, dept d8 WHERE d.deptno = e.deptno9 GROUP BY d.dname, to_char(e.hiredate, 'yyyy'))10 GROUP BY dname;DNAME CNT_80 CNT_81 CNT_82 CNT_83-------------- ---------- ---------- ---------- ----------ACCOUNTING 2 1RESEARCH 1 2 1 1SALES 6
如果有 N 个维度,一般需要通过 N 层分组来实现数据整合

SQL> SELECT *2 FROM (SELECT d.dname, to_char(e.hiredate, 'yyyy') hireyear3 FROM emp e, dept d4 WHERE d.deptno = e.deptno)5 pivot(COUNT(1)6 FOR hireyear IN(1980 AS cnt_807 ,1981 AS cnt_818 ,1982 AS cnt_829 ,1983 AS cnt_83));DNAME CNT_80 CNT_81 CNT_82 CNT_83-------------- ---------- ---------- ---------- ----------ACCOUNTING 0 2 1 0RESEARCH 1 2 1 1SALES 0 6 0 0
代码结构立刻清爽了不少,下面我们再板板正正的看一下 PIVOT 的语法



由于不同资料中的命名差别,轨道图中的 aggregate_function 对应语法结构图中的 pivot_clause
任何仅在 pivot_clause 中引用的列,都不能出现在 SELECT 列表中
任何仅在 pivot_for_clause 中引用的列,都不能出现在 SELECT 列表中
pivot_clause 中的所有列都必须使用聚集函数
SELECT *FROM (SELECT d.dname, to_char(e.hiredate, 'yyyy') hireyearFROM emp e, dept dWHERE d.deptno = e.deptno)pivot xml(COUNT(1) AS cntFOR hireyear IN(ANY));


SQL> SELECT * FROM emp_pivot;DNAME CNT_80 CNT_81 CNT_82 CNT_83-------------- ---------- ---------- ---------- ----------ACCOUNTING 0 2 1 0RESEARCH 1 2 1 1SALES 0 6 0 0
一般方法实现列转行
SQL> SELECT p.dname, 1980 hireyear, p.cnt_80 cnt2 FROM emp_pivot p3 UNION ALL4 SELECT p.dname, 1981 hireyear, p.cnt_81 cnt5 FROM emp_pivot p6 UNION ALL7 SELECT p.dname, 1982 hireyear, p.cnt_82 cnt8 FROM emp_pivot p9 UNION ALL10 SELECT p.dname, 1983 hireyear, p.cnt_83 cnt11 FROM emp_pivot p;DNAME HIREYEAR CNT-------------- ---------- ----------ACCOUNTING 1980 0RESEARCH 1980 1SALES 1980 0ACCOUNTING 1981 2RESEARCH 1981 2SALES 1981 6ACCOUNTING 1982 1RESEARCH 1982 1SALES 1982 0ACCOUNTING 1983 0RESEARCH 1983 1SALES 1983 012 rows selected
使用 UNPIVOT
SQL> SELECT *2 FROM emp_pivot3 unpivot(cnt FOR hireyear IN(cnt_80 AS 19804 ,cnt_81 AS 19815 ,cnt_82 AS 19826 ,cnt_83 AS 1983));DNAME HIREYEAR CNT-------------- ---------- ----------ACCOUNTING 1980 0ACCOUNTING 1981 2ACCOUNTING 1982 1ACCOUNTING 1983 0RESEARCH 1980 1RESEARCH 1981 2RESEARCH 1982 1RESEARCH 1983 1SALES 1980 0SALES 1981 6SALES 1982 0SALES 1983 012 rows selected
胜负一目了然


同理,语法结构图中的 unpivot_clause 对应轨道图中圈出的部分,unpivot_for_clause 对应轨道图中的 pivot_for_clause


文章转载自SQL干货分享,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




