You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle子表行转逗号分隔值遇重复数据的问题及解决方法

问题原因分析
  • 主查询关联子表触发重复行:你原查询里的where employee.id = trainings.employeeId(+)是Oracle旧版外连接语法,会让Employee表的行与对应Trainings表的行做匹配。若一个员工有N条培训记录,主查询就会输出N条完全相同的员工数据,最终结果呈现重复行。
  • 多表关联放大重复问题:实际场景中关联多表时,如果其他关联表是一对多关系,多表关联产生的笛卡尔积会进一步增加重复行的数量。
无需GROUP BY的子查询去重方案

1. 修正主查询逻辑,消除基础重复

去掉主查询对Trainings表的关联,子查询本身已通过tr.employee_id = employee.id完成员工与培训的关联,无需主查询额外关联。同时如果Trainings表存在同一员工的重复培训名称,在LISTAGG中加入DISTINCT实现字符串内去重:

select 
    id as Id, 
    name as Name, 
    (select listagg(distinct tr.name, ',') within group(order by tr.id) 
     from trainings tr 
     where tr.employee_id = employee.id) as Trainings 
from employee;

该查询中主查询仅从Employee表获取唯一员工行,子查询负责聚合该员工的培训名称,不会产生重复数据。

2. 多表关联场景的适配处理

若需要关联其他表(如部门、项目等),为避免其他一对多表引发的重复,可先通过子查询获取Employee的唯一行,再关联其他表:

select 
    e.id as Id, 
    e.name as Name, 
    d.dept_name as Department,
    -- 其他动态选择的列
    (select listagg(distinct tr.name, ',') within group(order by tr.id) 
     from trainings tr 
     where tr.employee_id = e.id) as Trainings 
from (
    -- 先获取员工唯一行,规避多表关联带来的重复
    select distinct id, name /* 这里包含所有需要动态选择的Employee表列 */ from employee
) e
left join department d on e.id = d.employee_id
-- 其他表关联逻辑
;

通过select distinct在子查询中确保员工行唯一,再关联其他表就不会出现重复的员工数据,同时子查询的LISTAGG依然负责生成去重后的培训字符串。

内容的提问来源于stack exchange,提问作者coder12349

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:53:18