zoukankan      html  css  js  c++  java
  • 行转列:总结


    行转列之一 太简单不说了


    例1:
     1  with v_data as
     2  (select '306A' certsn, 'A' type, '10951580' value, 20080504 notbefore, 20170803 notafter    from dual  union
     3   select '48C6' certsn, 'B' type, 'X,2,10013856' value, 20090629 notbefore, 20180616 notafter    from dual  union
     4   select '48C6' certsn, 'A' type, '11260221' value, 20090629 notbefore, 20180616 notafter    from dual)
     5 select certsn,
     6        case when v_data.type = 'A' then max(value) else ' ' end A,
     7        case when v_data.type = 'B' then max(value) else ' ' end B,
     8        max(notbefore) notbefore,
     9        max(notafter) notafter
    10   from v_data
    11  group by certsn, type;

    结果: 

    转置成
     


    行转列之二 wm_concat()


    例1:
    wm_concat()行转列并且用逗号分隔, 需要分组!
    1 select wm_concat(ename), --结果为类型clob
    2        to_char(wm_concat(ename)),
    3        dbms_lob.substr(wm_concat(ename), 4000)
    4   from emp
    5  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(order by rownum) from test group by c;


     

    行转列之三 listtagg()


    Oracle 转门的行转置函数 listagg()
    用法就像聚合函数一样,通过Group by语句,把每个Group的一个字段,拼接起来。非常方便。
     
    语法:
           LISTAGG(<转置列列表>, '分隔符' ) WITHIN GROUP( ORDER BY <排序列列表>) 
           GROUP BY ...
     
    例子:
    源数据为
     
     
    行转列:
    方法1)使用group by分组
     1 with temp as (  
     2   select 'China' nation ,'Guangzhou' city from dual union all  
     3   select 'China' nation ,'Shanghai'  city from dual union all  
     4   select 'China' nation ,'Beijing'   city from dual union all  
     5   select 'USA'   nation ,'New York'  city from dual union all  
     6   select 'USA'   nation ,'Bostom'    city from dual union all  
     7   select 'Japan' nation ,'Tokyo'     city from dual  
     8 )  
     9 select nation,listagg(city,',') within GROUP (order by city)  
    10 from temp  
    11 group by nation;

    结果:

    方法2)不使用分组, 使用listagg + over ( partition by 分组列)

    with temp as(  
      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一致!

     


    (转发)行转列之四 xmlagg() + xmlparse() + group by


    为解决 listagg() 字符串连接的结果过长问题
    语法:
    listagg(<转置列>, '<连接符>') within GROUP (order by <排序列>)
    等价于
    xmlagg(xmlparse(content <转置列> || '<连接符>' wellformed) order by <排序列>).getstringval()
    拍序列随意
     
    例3.1:
     1 with temp as(  
     2   select 'China' nation ,'Guangzhou' city from dual union all  
     3   select 'China' nation ,'Shanghai' city from dual union all  
     4   select 'China' nation ,'Beijing' city from dual union all  
     5   select 'USA' nation ,'New York' city from dual union all  
     6   select 'USA' nation ,'Bostom' city from dual union all  
     7   select 'Japan' nation ,'Tokyo' city from dual  
     8 )  
     9 select nation, --转置列
    10       listagg(city,',') within GROUP (order by city) as listagg,
    11       xmlagg(xmlparse(content city || ',' wellformed) order by city).getstringval(), 
    12       to_char(substr(xmlagg(xmlparse(content city || ',' wellformed) order by city).getclobval(),1,4000)) --!!!
    13       -- .getclobval() 结果集类型为clob 用 to_char()转置 
    14  from temp  
    15 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:取一张表的所有字段

    1 select max(substr(SYS_CONNECT_BY_PATH(COLUMN_NAME, ','), 2)) col
    2   from (select COLUMN_NAME, column_id
    3           from user_tab_columns
    4         where table_name = upper('&表名'))
    5 start with column_id = 1
    6 connect by column_id = rownum;
    其中:
    • SYS_CONNECT_BY_PATH(COLUMN_NAME, ',')  --取表的所有列名, ','逗号分隔
    • substr(SYS_CONNECT_BY_PATH(COLUMN_NAME, ','), 2) --去除第一个多余的','
    • max(substr(SYS_CONNECT_BY_PATH(COLUMN_NAME, ','), 2)) --全表分区取max,即取最长的一条,即取出表的所有列名 , 且返回的是串类型的 不是clob类型的
     
    例3.2:源数据为
     
    使用sys_connect_by_path() 开始"拼接"
    1 with v_data as (
    2   select ename v from emp where rownum < 5
    3 ) ,v_row_data as (
    4   select rownum rn,t.* FROM v_data t
    5 ) select rn,v,sys_connect_by_path(v,',') FROM v_row_data r 
    6 start with rn = 1
    7 connect by level = rn ;

    start with 子句是必须的

    上面结果:

     

    随后取"转置"的行(最长的一行),start with 使用了子查询
    1 with v_data as (
    2   select ename v from emp where rownum < 5
    3 ) ,v_row_data as (
    4   select rownum rn,t.* FROM v_data t
    5 ) select max(trim(leading ',' from sys_connect_by_path(v,','))) FROM v_row_data r 
    6 start with rn = (select min(rn) from v_row_data) --start with 使用了子查询
    7 connect by level = rn ;

    结果:



     

     
  • 相关阅读:
    Linux 信号signal处理机制
    va_start、va_arg、va_end、va_copy 可变参函数
    辛星笔记——VIM学习篇(推荐阅读)
    每个程序员都应该读的书
    igmpproxy源代码学习——配置信息加载 loadConfig
    windows下gvim搭建IDE
    插入排序与循环不变式
    6个变态的C语言程序
    安卓原生百度地图(5)导航和语音播报
    安卓原生百度地图(4)路线规划
  • 原文地址:https://www.cnblogs.com/xhwy2940/p/7421934.html
Copyright © 2011-2022 走看看