SQL/PLSQL:行转列总结_20170822
来源:互联网 发布:淘宝app打开很慢 编辑:程序博客网 时间:2024/06/03 17:58
行转列之零 group by + case 太简单不细说了
例1:
with v_data as (select '306A' certsn, 'A' type, '10951580' value, 20080504 notbefore, 20170803 notafter from dual union select '48C6' certsn, 'B' type, 'X,2,10013856' value, 20090629 notbefore, 20180616 notafter from dual union select '48C6' certsn, 'A' type, '11260221' value, 20090629 notbefore, 20180616 notafter from dual)select certsn, case when v_data.type = 'A' then max(value) else ' ' end A, case when v_data.type = 'B' then max(value) else ' ' end B, max(notbefore) notbefore, max(notafter) notafter from v_data group by certsn, type;
结果
行转列之一 wm_concat()
例1:
wm_concat()行转列并且用逗号分隔, 需要分组!
select wm_concat(ename), --结果为类型clob
to_char(wm_concat(ename)),
dbms_lob.substr(wm_concat(ename), 4000)
from emp
where rownum < 5;
结果:
例2:
select c, listagg(a,'') within group(order by rownum) from test group by c;
with test as (
select 1 c,'西' a from dual union all
select 1 c,'安' a from dual union all
select 1 c,'的' a from dual union all
select 2 c,'天' a from dual union all
select 2 c,'气' a from dual union all
select 3 c,'好' a from dual
)
select c, replace(to_char(wm_concat(a)),',','') FROM test group by c;
结果:
或者
select c, listagg(a,'') within group(orderby rownum)from testgroupby c;
行转列之二 listtagg()
Oracle 转门的行转置函数 listagg()
语法:
LISTAGG(XXX,XXX) WITHIN GROUP( ORDER BY XXX) GROUP BY ...
用法就像聚合函数一样,通过Group by语句,把每个Group的一个字段,拼接起来。非常方便。
例子:
源数据为
行转列:
1)使用group by分组
with temp as(
select 'China' nation ,'Guangzhou' city from dual union all
select 'China' nation ,'Shanghai' city from dual union all
select 'China' nation ,'Beijing' city from dual union all
select 'USA' nation ,'New York' city from dual union all
select 'USA' nation ,'Bostom' city from dual union all
select 'Japan' nation ,'Tokyo' city from dual
)
select nation,listagg(city,',') within GROUP (order by city)
from temp
group by nation;
2)高级用法不使用group by分组的情况:
使用分析函数, 即listagg + over(paratition by 分组列)
with tempas(
select 'China' nation ,'Guangzhou' city from dual union all
...
)
select --nation, listagg(city,',') within GROUP (order by city) over (partition by nation) rank --使用分析函数代替分组
distinct nation, listagg(city,',') within GROUP (order by city) over (partition by nation) rank --去重!
from temp
order by nation;
结果和上面SQL一致!
总结:LISTAGG()把它当作SUM()函数来使用就可以了。
(转发)行转列之三 xmlagg() + xmlparse()
为解决 listagg() 字符串连接的结果过长问题
语法:
listagg(<转置列>, '<连接符>') within GROUP (order by <排序列>)
等价于
xmlagg(xmlparse(content <转置列> || '<连接符>' wellformed) order by <排序列>).getstringval()
拍序列随意
还是上面例子:
with temp as(
select 'China' nation ,'Guangzhou' city from dual union all
select 'China' nation ,'Shanghai' city from dual union all
select 'China' nation ,'Beijing' city from dual union all
select 'USA' nation ,'New York' city from dual union all
select 'USA' nation ,'Bostom' city from dual union all
select 'Japan' nation ,'Tokyo' city from dual
)
select nation, --转置列
listagg(city,',') within GROUP (order by city) as listagg,
xmlagg(xmlparse(content city || ',' wellformed) order by city).getstringval(),
to_char(substr(xmlagg(xmlparse(content city || ',' wellformed) order by city).getclobval(),1,4000)) --!!!
-- .getclobval() 结果集类型为clob 用 to_char()转置
from temp
group by nation;
例3.2:
select xmlagg(xmlparse(content wm_concat(ename) || ', ' wellformed) order by 1) .getstringval() from emp where rownum < 5 group by '必须有'; --分组列这里无所谓但必须要结果:
行转列之四 SYS_CONNECT_BY_PATH()
层次查询中
函数 SYS_CONNECT_BY_PATH(列名,'连接符') 能取回叶子节点到根节点的全路径
例子3.1:取一张表的所有字段
select max(substr(SYS_CONNECT_BY_PATH(COLUMN_NAME, ','), 2)) col
from (select COLUMN_NAME, column_id
from user_tab_columns
where table_name = upper('&表名'))
start with column_id = 1
connect by column_id = rownum;
其中:
1)SYS_CONNECT_BY_PATH(COLUMN_NAME, ',') --取表的所有列名, ','逗号分隔
2)substr(SYS_CONNECT_BY_PATH(COLUMN_NAME, ','), 2) --去除第一个多余的','
3)max(substr(SYS_CONNECT_BY_PATH(COLUMN_NAME, ','), 2)) --全表分区取max,即取最长的一条,即取出表的所有列名 , 且返回的是串类型的 不是clob类型的
例3.2:源数据为
使用sys_connect_by_path() 开始"拼接"
start with 子句是必须的
with v_data as (
select ename v from emp where rownum < 5
) ,v_row_data as (
select rownum rn,t.* FROM v_data t
) select rn,v,sys_connect_by_path(v,',') FROM v_row_data r
start with rn = 1
connect by level = rn ;
行转列: 最终版,start with 使用了子查询
with v_data as (
select ename v from emp where rownum < 5
) ,v_row_data as (
select rownum rn,t.* FROM v_data t
) select max(trim(leading ',' from sys_connect_by_path(v,','))) FROM v_row_data r
start with rn = (select min(rn) from v_row_data) --start with 使用了子查询
connect by level = rn ;
阅读全文
0 0
- SQL/PLSQL:行转列总结_20170822
- SQL/PLSQL:日期函数总结_20170822
- SQL/PLSQL:日期函数总结
- PLSQL总结——18.动态SQL
- sql plsql
- PLSQL总结
- plsql 总结
- Sql/PLSql随记
- plsql常用命令大全 sql
- PLSQL批量导入sql
- plsql-动态sql
- SQL/PLSQL基础
- plsql 格式化sql 语句
- SQL和PLSQL
- PLSQL 拼接SQL
- plsql 导出 sql脚本
- sql/PLsql基础1
- 浅谈SQL与PLSQL
- Linux之多线程及互斥锁pthread_mutex_t的学习
- TensorFlow内存管理bfc算法
- 学编程,你不能学会了游泳再下水
- vue中的报错情况
- 解决POI读取Excel内存溢出的问题
- SQL/PLSQL:行转列总结_20170822
- Spring AOP详解
- MATLAB 牛顿迭代法解非线性方程组
- ubuntu16.04耳机没声音解决
- PAT-A 1006. Sign In and Sign Out (25)
- 尾调用优化
- iOS Xcode工程目录的 folder 和 group的区别
- JMS简单原理
- google通信协议probuf的使用