理解listagg函數


兩道SQL面試題引出listagg函數:

   1. 用一條sql求出每個部門(emp表)的最大工資和最小工資,以及最大工資和最小工資的員工姓名。   

(注:一次表掃描。同一個部門最大工資或最小工資的人可能不止一個)。   

2. 需求:有時為了方便打印,會要求多行多列打印,如打印emp.ename列,類似下面這樣顯示:    

                     ALLEN  JONES  MARTIN  SMITH    WARD                         

                     BLAKE  CLARK  KING    SCOTT  TURNER                         

                     ADAMS FORD   JAMES     MILLER

 

listagg函數是oracle11.2以后推出的一個新函數,使用該函數實現了行轉列的功能,該數據與wmsys.wm_concat函數功能類似。
簡單的說就是在分組合並后,把某列數據逐個枚舉出來,其實也是一個行轉列的效果。

如下,原始數據:

實現效果:

 

sql語句舉例說明:

select nation,  listagg(city,',') within group (order by  city) as city  

from test  

group by nation

1:使用該函數必須的進行分組(group by 或使用分析函數進行分組)
2:listagg函數第一個參數表示需要進行枚舉的字段,第二個參數表示枚舉數據的分隔符
3:對於枚舉的字段同時還需要排序和分組within group(order by xx)

 

利用網絡上的例子:

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)  city
from temp  
group by nation;

 

 

--利用wmsys.wm_concat實現相似的效果

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,wmsys.wm_concat(city) 
from temp  
group by nation;

 

 

wmsys.wm_concat函數默認枚舉的數據是','分隔開的,而listagg可以自定義分隔符

 

--利用over(partition by XXX) 分析函數實現分組產生以上效果

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) over (partition by nation) city  
from temp;

 

 

listagg函數作為分析函數的一部分存在。

 

理解完listagg函數上面的面試題也就容易多了,如下:

   1. 用一條sql求出每個部門(emp表)的最大工資和最小工資,以及最大工資和最小工資的員工姓名。
   (注:一次表掃描。同一個部門最大工資或最小工資的人可能不止一個)。

   select  deptno,
         max(sal) max_sal,
         listagg(decode(rn1, 1, ename, null), ',') within group(order by ename) max_sal_ename,
         min(sal) min_sal,
        listagg(decode(rn2, 1, ename, null), ',') within group(order by ename) min_sal_ename
 from
 (select deptno,
         ename,
         sal,
        dense_rank() over(partition by deptno order by sal desc) rn1,
        dense_rank() over(partition by deptno order by sal) rn2
   from emp)
where rn1 = 1 or rn2 = 1
group by deptno;

 

   2. 需求:有時為了方便打印,會要求多行多列打印,如打印emp.ename列,類似下面這樣顯示:
    ALLEN  JONES  MARTIN  SMITH    WARD
    BLAKE  CLARK  KING       SCOTT  TURNER
    ADAMS FORD   JAMES     MILLER

    select deptno,listagg(ename,',') within group(order by ename)  
from emp t group by t.deptno;

select wmsys.wm_concat(listagg(ename,',') within group(order by ename))  
from emp t group by t.deptno;

 

 

 

參考:
http://www.2cto.com/database/201304/204096.html
http://www.2cto.com/database/201210/161494.html
http://dacoolbaby.iteye.com/blog/1698957
http://www.itpub.net/thread-1912275-1-1.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM