2. 11g 自带的行列转换
旁边那个带眼镜,说的就是你,眼珠子直勾勾的怎么了?上面的没看懂? 要是以前,我老先生就得语重心长地教育你,那么重要的东西没看懂,将来想不想换工作了?但现在这话就说不出口了,因为11g的SQL自己就带这个了。
11g在SELECT语句中新加了关键词PIVOT和UNPIVOT,用这两个关键词,重写上面的两个查询,就变成这个样子的了:
行变列:
SELECT * FROM emp_phone
PIVOT (
MAX(phone) for type IN (1 as home, 2 as office, 2 as mobile)
)
/
PIVOT以后的字句都是新加的。但万变不离其宗,还是要用到分组函数。IN后边是按type的不同值映射成不同的列。简单吧?
列变行,这是UNPIVOT的工作,写法如下:
SELECT * FROM emp_phone_x UNPIVOT ( phone FOR type in (HOME AS 1, OFFICE AS 2, MOBILE AS 3) ) / 这里是把不同的列转换成不同的type的数值。 再用SCOTT用户里的EMP表做个例子,列出各部门之间工资总和: SELECT * FROM ( (SELECT sal, deptno FROM emp) PIVOT ( SUM(sal) FOR deptno IN (10 as dept_10, 20 as dept_20, 30 as dept_30) ) ) / DEPT_10 DEPT_20 DEPT_30 ---------- ---------- ---------- 8750 10875 9400
再往深里想,前边的所有例子都有一个局限,电话的type和emp的deptno都是有限的、可穷举的。如果这些列都是可随时可添加的,又该怎么办呢?11g以前肯定是要动用动态SQL的法宝。那11g又是怎么处理的呢?刚看SQL参考手册的时候,看到里边豁然写着IN后边可以接子查询或ANY,当时是佩服的眼泪哗哗的,迫不及待赶紧试一试:
SELECT * FROM ( (SELECT sal, deptno FROM emp) PIVOT ( SUM(sal) FOR deptno IN (SELECT deptno FROM dept) ) ) / ERROR at line 5: ORA-00936: missing expression SELECT * FROM ( (SELECT sal, deptno FROM emp) PIVOT ( SUM(sal) FOR deptno IN (ANY) ) ) / ERROR at line 5: ORA-00936: missing expression
这一下又变成拔凉拔凉的,这么大个ORACLE也不能无耻到这个地步吧?正准备再确认一下手册,抓他个人赃俱获,突然有发现里边豁然写着:
A subquery is used only in conjunction with the XML keyword… The ANY keyword is used only in conjunction with the XML keyword… 学习不认真,该打。原来是给生成XML串用的,正确用法如下: SELECT * FROM ( (SELECT sal, deptno FROM emp) PIVOT XML ( SUM(sal) FOR deptno IN (ANY) ) ) <PivotSet><item><column name = "DEPTNO">10</column>
<column name = "SUM(SAL)">8750</column></item><item>
<column name = "DEPTNO">20</column><column name = "SUM(SAL)">10875</column></item><item>
<column name = "DEPTNO">30</column><column name = "SUM(SAL)">9400</column></item></PivotSet>
这个东西的结果具体怎么用就留给大家做作业了。反正XML咱也不熟,借这个机会就下了。。。