2.1_4 Oralce LISTAGG函数【列转行 多列 -> 一列(指定分隔符)】


相关链接


前言

碰到此类情况 ,需要将多列数据合并成为一列时,可以采用LISTAGG聚合函数

NATION|CITY     |  	  => 	NATION|CITIES                    |
------|---------|  	  =>	------|--------------------------|
China |Guangzhou|  	  =>	China |Beijing,Guangzhou,Shanghai|
China |Shanghai |  	  =>	Japan |Tokyo                     |
China |Beijing  |  	  =>	USA   |Bostom,New York           |
USA   |New York |
USA   |Bostom   |
Japan |Tokyo    |

(wc_concat也可以达到同样效果,但测试用的11g版本好像不支持wmsys.wm_concat函数,没有深入研究)

  • Oracle 环境
--执行SQL
SELECT * FROM V$VERSION;

--返回结果
BANNER                                                                      |
----------------------------------------------------------------------------|
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production|
PL/SQL Release 11.2.0.4.0 - Production                                      |
CORE 11.2.0.4.0 Production                                                  |
TNS for Linux: Version 11.2.0.4.0 - Production                              |
NLSRTL Version 11.2.0.4.0 - Production                                      |

LISTAGG()语法

  • 基础用法 - 参数
    • column :待合并字段
    • separator : 分隔符,两端需要加单引号
    • sortCol:组内排序字段
LISTAGG(${column},'${separator}') WITHIN GROUP(ORDER BY ${sortCol})

注:LISTAGG属于聚合函数,只能和其他聚合函数(SUM,AVG等),或GROUP BY字段一起查询

--执行SQL
SELECT 
	T.SAL,
	LISTAGG(T.ENAME,',') WITHIN GROUP(ORDER BY T.ENAME)
FROM SCOTT.EMP T

--返回结果
org.jkiss.dbeaver.model.sql.DBSQLException: SQL 错误 [937] [42000]: ORA-00937: 不是单组分组函数
  • 进阶用法 ( + 开窗函数 )
LISTAGG(${column},'${separator}') WITHIN GROUP(ORDER BY ${sortCol}) OVER (PARTITION BY 分组字段)

实例1 SCOTT.EMP

  • 查看表
--执行SQL
SELECT * FROM SCOTT.EMP

--返回结果
EMPNO|ENAME |JOB      |MGR |HIREDATE           |SAL |COMM|DEPTNO|
-----|------|---------|----|-------------------|----|----|------|
 7369|SMITH |CLERK    |7902|1980-12-17 00:00:00| 800|    |    20|
 7499|ALLEN |SALESMAN |7698|1981-02-20 00:00:00|1600| 300|    30|
 7521|WARD  |SALESMAN |7698|1981-02-22 00:00:00|1250| 500|    30|
 7566|JONES |MANAGER  |7839|1981-04-02 00:00:00|2975|    |    20|
 7654|MARTIN|SALESMAN |7698|1981-09-28 00:00:00|1250|1400|    30|
 7698|BLAKE |MANAGER  |7839|1981-05-01 00:00:00|2850|    |    30|
 7782|CLARK |MANAGER  |7839|1981-06-09 00:00:00|2450|    |    10|
 7788|SCOTT |ANALYST  |7566|1987-04-19 00:00:00|3000|    |    20|
 7839|KING  |PRESIDENT|    |1981-11-17 00:00:00|5000|    |    10|
 7844|TURNER|SALESMAN |7698|1981-09-08 00:00:00|1500|   0|    30|
 7876|ADAMS |CLERK    |7788|1987-05-23 00:00:00|1100|    |    20|
 7900|JAMES |CLERK    |7698|1981-12-03 00:00:00| 950|    |    30|
 7902|FORD  |ANALYST  |7566|1981-12-03 00:00:00|3000|    |    20|
 7934|MILLER|CLERK    |7782|1982-01-23 00:00:00|1300|    |    10|

练习1.1

  • 不分组,按逗号分隔,组内按员工姓名排序
--执行SQL
SELECT 
	LISTAGG(T.ENAME,',') WITHIN GROUP(ORDER BY T.ENAME) AS ENAMES
FROM SCOTT.EMP T

--返回结果
ENAMES                                                                             |
-----------------------------------------------------------------------------------|
ADAMS,ALLEN,BLAKE,CLARK,FORD,JAMES,JONES,KING,MARTIN,MILLER,SCOTT,SMITH,TURNER,WARD|

练习1.2

  • 按JOB分组,按逗号分隔,组内按员工姓名(ENAME)排序
--执行SQL
SELECT 
	T.JOB,
	LISTAGG(T.ENAME,',') WITHIN GROUP(ORDER BY T.ENAME) AS ENAMES
FROM SCOTT.EMP T
GROUP BY T.JOB

--返回结果
 JOB     |ENMAES                                         |
---------|-----------------------------------------------|
ANALYST  |FORD,SCOTT                                     |
CLERK    |ADAMS,JAMES,MILLER,SMITH                       |
MANAGER  |BLAKE,CLARK,JONES                              |
PRESIDENT|KING                                           |
SALESMAN |ALLEN,MARTIN,TURNER,WARD                       |

练习1.3

  • 按JOB分组,按逗号分隔,组内按工资(SAL)排序
--执行SQL
SELECT 
	T.JOB,
	LISTAGG(T.ENAME,',') WITHIN GROUP(ORDER BY T.SAL) AS ENMAES,
	LISTAGG(T.SAL,',') WITHIN GROUP(ORDER BY T.SAL) AS SALS
FROM SCOTT.EMP T
GROUP BY T.JOB

--返回结果
JOB      |ENMAES                                       |SALS                                       |
---------|---------------------------------------------|-------------------------------------------|
ANALYST  |FORD,SCOTT                                   |3000,3000                                  |
CLERK    |SMITH,JAMES,ADAMS,MILLER                     |800,950,1100,1300                          |
MANAGER  |CLARK,BLAKE,JONES                            |2450,2850,2975                             |
PRESIDENT|KING                                         |5000                                       |
SALESMAN |MARTIN,WARD,TURNER,ALLEN                     |1250,1250,1500,1600                        |

实例2 虚表DUAL

  • 查看表
--执行SQL
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

--返回结果
NATION|CITY     |
------|---------|
China |Guangzhou|
China |Shanghai |
China |Beijing  |
USA   |New York |
USA   |Bostom   |
Japan |Tokyo    |

练习2.1

  • 按国家分组,按逗号分隔,组内按城市名(CITY)称排序
--执行SQL
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 CITIES
FROM temp 
GROUP BY nation

--返回结果
NATION|CITIES                                   |
------|-----------------------------------------|
China |Beijing,Guangzhou,Shanghai               |
Japan |Tokyo                                    |
USA   |Bostom,New York                          |

练习2.2 LISTAGG 高阶用法

  • LISTAGG + 开窗函数 OVER PARTITION BY
--执行SQL
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) AS CITIES
FROM temp 
ORDER BY NATION

--返回结果
NATION|CITIES                    |
------|--------------------------|
China |Beijing,Guangzhou,Shanghai|
China |Beijing,Guangzhou,Shanghai|
China |Beijing,Guangzhou,Shanghai|
Japan |Tokyo                     |
USA   |Bostom,New York           |
USA   |Bostom,New York           |


--执行SQL
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 DISTINCT
	nation,
	LISTAGG(city,',') WITHIN GROUP (ORDER BY city) OVER (PARTITION BY nation) AS CITIES
FROM temp 
ORDER BY NATION

--返回结果
NATION|CITIES                    |
------|--------------------------|
China |Beijing,Guangzhou,Shanghai|
Japan |Tokyo                     |
USA   |Bostom,New York           |

参考文章


20/08/21

M

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值