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版本的官方文档。

相关推荐
听闻风很好吃2 分钟前
DAY9:Oracle数据库安全管理深度解析
oracle
LucianaiB37 分钟前
【金仓数据库征文】_AI 赋能数据库运维:金仓KES的智能化未来
运维·数据库·人工智能·金仓数据库 2025 征文·数据库平替用金仓
时序数据说1 小时前
时序数据库IoTDB在航空航天领域的解决方案
大数据·数据库·时序数据库·iotdb
.生产的驴1 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
AnsenZhu1 小时前
2025年Redis分片存储性能优化指南
数据库·redis·性能优化·分片
oydcm2 小时前
MySQL数据库概述
数据库·mysql
oioihoii2 小时前
C++23中if consteval / if not consteval (P1938R3) 详解
java·数据库·c++23
带娃的IT创业者2 小时前
《AI大模型趣味实战》基于RAG向量数据库的知识库AI问答助手设计与实现
数据库·人工智能
husterlichf3 小时前
MYSQL 常用数值函数 和 条件函数 详解
数据库·sql·mysql
我的golang之路果然有问题3 小时前
快速了解redis,个人笔记
数据库·经验分享·redis·笔记·学习·缓存·内存