Oracle字符串聚合函数LISTAGG

在Oracle 19c中,LISTAGG函数是一个非常有用的字符串聚合函数,它可以将来自多个行的值连接成一个单独的字符串。这个函数特别适用于将分组内的多个值合并为一个逗号分隔(或其他分隔符)的字符串。

LISTAGG函数的基本语法如下:

sql 复制代码
LISTAGG(column, [delimiter]) WITHIN GROUP (ORDER BY order_by_clause) [OVER(PARTITION BY paration_by_clause) ]
  • column 是你想要聚合的列。
  • [delimiter] 是可选的,用于指定值之间的分隔符,默认为NULL。如果不指定分隔符,则所有值将直接连接在一起,没有分隔。
  • WITHIN GROUP (ORDER BY order_by_clause) 是必须的,用于指定聚合时值的排序方式。
  • OVER(PARTITION BY XXX) 在不使用GROUP BY语句时候,也可以使用LISTAGG函数

示例1

假设我们有一个名为employees的表,其中包含department_idemployee_name两个字段,我们想要为每个部门列出所有员工的名字,名字之间用逗号分隔。

sql 复制代码
SELECT
    department_id,
    LISTAGG(employee_name, ', ') WITHIN GROUP (ORDER BY employee_name) AS employees
FROM
    employees
GROUP BY
    department_id;

这个查询将返回每个部门的ID和该部门所有员工名字的列表,名字之间用逗号加空格分隔。

示例2

sql 复制代码
SYS@orcl> create table t_listagg(id number,nation varchar2(32),city varchar2(128),constraint pk_t_listagg_id primary key(id));

Table created.

INSERT INTO t_listagg
select 1 ID,'China' nation ,'广州' city from dual union all 
select 2 ID,'China' nation ,'深圳' city from dual union all  
select 3 ID,'China' nation ,'上海' city from dual union all  
select 4 ID,'China' nation ,'北京' city from dual union all  
select 5 ID,'USA' nation ,'New York' city from dual union all  
select 6 ID,'USA' nation ,'Boston' city from dual union all  
select 7 ID,'Japan' nation ,'Tokyo' city from dual  
COMMIT;

SYS@orcl> col city format a30
SYS@orcl> select * from t_listagg;

        ID NATION                           CITY
---------- -------------------------------- ------------------------------
         1 China                            广州
         2 China                            深圳
         3 China                            上海
         4 China                            北京
         5 USA                              New York
         6 USA                              Boston
         7 Japan                            Tokyo

SYS@orcl> col LISTAGG_CITY format a60
SYS@orcl> set linesize 200
-- 用于指定聚合时值的,以city升序方式排序
SYS@orcl> select nation,listagg(city,',') within GROUP (order by city) listagg_city  FROM t_listagg  GROUP by nation;

NATION                           LISTAGG_CITY
-------------------------------- ------------------------------------------------------------
China                            上海,北京,广州,深圳
Japan                            Tokyo
USA                              Boston,New York
-- 用于指定聚合时值的,以ID倒序方式排序
SYS@orcl> select nation,listagg(city,',') within GROUP (order by ID desc) listagg_city  FROM t_listagg  GROUP by nation;

NATION                           LISTAGG_CITY
-------------------------------- ------------------------------------------------------------
China                            北京,上海,深圳,广州
Japan                            Tokyo
USA                              Boston,New York

-- 用于指定聚合时值的,以ID倒序方式排序,以nation分组
SYS@orcl> select id,nation,city,listagg(city,',') within GROUP (order by id desc)  over (partition by nation) rank  FROM t_listagg;

        ID NATION                           CITY                           RANK
---------- -------------------------------- ------------------------------ ------------------------------------------------------------
         4 China                            北京                           北京,上海,深圳,广州
         3 China                            上海                           北京,上海,深圳,广州
         2 China                            深圳                           北京,上海,深圳,广州
         1 China                            广州                           北京,上海,深圳,广州
         7 Japan                            Tokyo                          Tokyo
         6 USA                              Boston                         Boston,New York
         5 USA                              New York                       Boston,New York

7 rows selected.

注意事项

  1. 字符串长度限制LISTAGG函数在Oracle中有字符串长度的限制。在Oracle 12c及之前的版本中,这个限制是4000字节。从Oracle 12c Release 2开始,可以通过设置ON OVERFLOW TRUNCATE子句来处理超出长度的情况,但Oracle 19c仍然默认有这个限制。如果聚合的字符串超过了这个长度,查询将失败。

  2. 处理超长字符串 :如果你预期聚合的字符串可能会超过4000字节的限制,你可以考虑使用XMLAGGXMLELEMENT函数作为替代方案,因为XMLAGG不受此限制。但是,请注意,使用XMLAGG会使查询更加复杂,并且可能需要额外的处理来将XML类型的结果转换为字符串。

  3. 性能 :对于大型数据集,LISTAGG函数可能会影响查询性能。在可能的情况下,考虑使用索引、优化查询逻辑或考虑数据聚合的替代方法。

  4. 版本兼容性 :虽然LISTAGG在Oracle 11g Release 2及更高版本中可用,但某些特性(如ON OVERFLOW TRUNCATE)可能在较新的版本中才可用。始终参考你正在使用的Oracle版本的官方文档。

相关推荐
MXsoft61844 分钟前
数据中心服务器与存储运维的深度实践与挑战
数据库
Fireworkitte1 小时前
MySQL常用的函数
数据库·mysql
qq_200337392 小时前
可以从以下几个方面判断一个 SQL 查询是否需要优化:
数据库
乐容2 小时前
14,子查询语句嵌套
数据库
cyt涛2 小时前
Redis访问工具
数据库·redis·spring cache·注解·客户端·lettuce·redistemplae
AllWe$2 小时前
九、Redis 的实际使用与Redis的设计
数据库·redis·缓存
u0133087093 小时前
大模型训练数据库Common Crawl
数据库·语言模型
一博一言3 小时前
Oracle Linux 8.10安装Oracle19c(19.3.0)完整教程
linux·oracle
杨浦老苏3 小时前
跨平台数据库管理软件SQLynx
数据库·docker·群晖
Flying_Fish_roe3 小时前
Java中NoSQL 与分布式数据库
java·数据库·nosql