数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

Oracle11gSQL新功能pivot/unpivot


发布日期:2021年06月29日
 
Oracle11gSQL新功能pivot/unpivot

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咱也不熟借这个机会就下了

上一篇:网络收集:PLSQL常用方法汇总

下一篇:快速转移数据的方法