Oracle SQL LISTAGG聚合出现重复结果的修复方法
Oracle LISTAGG聚合结果去重的可操作修复方案
重复值的核心来源分为两类:多表关联产生行数膨胀带出重复字段值、聚合维度下本身存在同值记录,以下是可直接落地的修复方案:
- 适配Oracle 19c及以上版本的快速修复
直接利用LISTAGG函数原生支持的DISTINCT关键字,在聚合环节直接过滤同组内的重复值,无需调整表关联逻辑。同步修复原SQL语法问题后的可执行代码:SELECT LISTAGG(DISTINCT A.name, ',') WITHIN GROUP (ORDER BY A.id) AS A, LISTAGG(DISTINCT B.name, ',') WITHIN GROUP (ORDER BY B.id) AS B FROM some_table JOIN A ON A.id = some_table.id JOIN B ON B.name = some_table.name WHERE some_table.status IN (1,2,3) GROUP BY some_table.id - 适配11g/12c等低版本Oracle的兼容修复
低版本LISTAGG不支持DISTINCT语法,需要提前对关联中间结果做去重,从根源上切断重复值的产生路径,同时避免关联带来的笛卡尔积拉低查询性能。修正后的代码:WITH filtered_base AS ( SELECT DISTINCT st.id AS main_id, A.id AS a_id, A.name AS a_name, B.id AS b_id, B.name AS b_name FROM some_table st -- 关联前先对维度表做去重,减少关联后的数据行数 JOIN (SELECT DISTINCT id, name FROM A) A ON A.id = st.id JOIN (SELECT DISTINCT name, id FROM B) B ON B.name = st.name WHERE st.status IN (1,2,3) ) SELECT LISTAGG(a_name, ',') WITHIN GROUP (ORDER BY a_id) AS A, LISTAGG(b_name, ',') WITHIN GROUP (ORDER BY b_id) AS B FROM filtered_base GROUP BY main_id
注意事项:
- 原SQL存在语法书写错误:
join B.name = some_table.name缺失关联表实体和ON关键字,无法直接执行,需要按上述代码补全关联逻辑。 - 若聚合后的拼接结果超过Oracle默认4000字节的字符串长度上限,12cR2及以上版本可在LISTAGG中追加
ON OVERFLOW TRUNCATE '...' WITH COUNT语法,避免触发字符串长度溢出报错。
内容的提问来源于stack exchange,提问作者Maya Saias
相关产品推荐
相关产品推荐

