g以前的行列转换
领袖又说了温故而知新那就让我们先看看g以前是怎么实现地行列转换一直当作甄别老手和新手的试金石面试的时候面试官不问这个都不好意思张嘴Itpub的Oracle开发版更是每隔十天半个月就有人问这个你说重要不重要
假设有表emp_phone如下
NAME
TYPE
PHONE
张三
张三
张三
李四
李四
马五u
马五
王二(没麻子)
表里放着张三李四王二麻子等等主人翁的电话号码(TYPE //分别对应家/办公室/手机)如果要把每个人的所有电话放在一行上就是行转列了结果如下
NAME
HOME
OFFICE
MOBILE
张三
李四
马五
王二(没麻子)
写这个SQL的技巧就是按姓名分组然后使每一组每一类的电话号码最多只有一个里边用到的分组函数都是聋子的耳朵-摆设用MAX可以MIN也行
这个查询写出来就是 SELECT
name
MAX(decode(type phone)) Home
MAX(decode(type phone)) Office
MAX(decode(type phone)) Mobile
FROM
emp_phone
GROUP BY
Name
/
那位看官说了能不能再变回去?能不能戏法不就漏了不是?
这儿要用到另一的技巧就是笛卡尔乘积将一行复制成三行每一行取一个类型的电话
偷个懒儿把上边的结果表叫emp_phone_x把列还原成行的SQL SELECT
NAME
DECODE (lvl home office mobile) phone
FROM
emp_phone_x
(SELECT LEVEL lvl
FROM DUAL
CONNECT BY LEVEL <= )
WHERE
DECODE (lvl home office mobile) IS NOT NULL /
g 自带的行列转换
旁边那个带眼镜说的就是你眼珠子直勾勾的怎么了?上面的没看懂? 要是以前我老先生就得语重心长地教育你那么重要的东西没看懂将来想不想换工作了?但现在这话就说不出口了因为g的SQL自己就带这个了
g在SELECT语句中新加了关键词PIVOT和UNPIVOT用这两个关键词重写上面的两个查询就变成这个样子的了
行变列 SELECT * FROM emp_phone
PIVOT (
MAX(phone) for type IN ( as home as office as mobile)
)
/
PIVOT以后的字句都是新加的但万变不离其宗还是要用到分组函数IN后边是按type的不同值映射成不同的列简单吧?
列变行这是UNPIVOT的工作写法如下 SELECT * FROM emp_phone_x
UNPIVOT (
phone FOR type in (HOME AS OFFICE AS MOBILE AS )
)
/
这里是把不同的列转换成不同的type的数值
再用SCOTT用户里的EMP表做个例子列出各部门之间工资总和 SELECT * FROM
(
(SELECT sal deptno FROM emp)
PIVOT (
SUM(sal) FOR deptno IN ( as dept_ as dept_ as dept_)
)
)
/
DEPT_ DEPT_ DEPT_
再往深里想前边的所有例子都有一个局限电话的type和emp的deptno都是有限的可穷举的如果这些列都是可随时可添加的又该怎么办呢?g以前肯定是要动用动态SQL的法宝那g又是怎么处理的呢?刚看SQL参考手册的时候看到里边豁然写着IN后边可以接子查询或ANY当时是佩服的眼泪哗哗的迫不及待赶紧试一试 SELECT * FROM
(
(SELECT sal deptno FROM emp)
PIVOT (
SUM(sal) FOR deptno IN (SELECT deptno FROM dept)
)
)
/
ERROR at line :
ORA: missing expression
SELECT * FROM
(
(SELECT sal deptno FROM emp)
PIVOT (
SUM(sal) FOR deptno IN (ANY)
)
)
/
ERROR at line :
ORA: 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></column>
<column name = SUM(SAL)></column>
</item>
<item>
<column name = DEPTNO></column>
<column name = SUM(SAL)></column>
</item>
<item>
<column name = DEPTNO></column>
<column name = SUM(SAL)></column>
</item>
</PivotSet>
这个东西的结果具体怎么用就留给大家做作业了反正XML咱也不熟借这个机会就下了