Oracle SQL中LISTAGG聚合重复名称去重及查询修正问询
解决LISTAGG返回重复姓名的问题
嘿,我来帮你搞定这个重复姓名的问题!咱们一步步来分析:
当前查询的问题
你的原查询之所以会返回重复姓名,核心原因是关联FILM_PRODUKCE表时产生了重复行。比如同一个人可能在同一部电影的FILM_PRODUKCE里有多条记录(比如兼任多个生产角色),当你直接和OSOBA表JOIN后,这些重复的记录会被保留,最终LISTAGG会把同一个名字多次拼接进去。
解决方案
根据你使用的Oracle版本,有两种简单的解决方式:
方式1:使用DISTINCT直接去重(Oracle 12cR2及以上版本支持)
如果你的Oracle版本是12cR2或更新的,直接在LISTAGG里加上DISTINCT关键字就能自动去重,这是最简洁的方法:
SELECT FILM.NAZEV, FILM.VYDANI, FILM.DELKA, FILM.CENA, LISTAGG(DISTINCT OSOBA.JMENO, ',') WITHIN GROUP (ORDER BY OSOBA.JMENO) AS Produkce FROM FILM_PRODEJNA INNER JOIN FILM ON FILM_PRODEJNA.FILM_ID_FILM = FILM.ID_FILM LEFT JOIN FILM_PRODUKCE ON FILM_PRODUKCE.FILM_ID_FILM = FILM.ID_FILM -- 补全你原语句未写完的关联条件 LEFT JOIN OSOBA ON FILM_PRODUKCE.OSOBA_ID_OSOBA = OSOBA.ID_OSOBA -- 假设关联OSOBA表的条件为该字段 GROUP BY FILM.NAZEV, FILM.VYDANI, FILM.DELKA, FILM.CENA;
方式2:子查询先去重(兼容所有Oracle版本)
如果你的Oracle版本不支持LISTAGG里的DISTINCT,可以先通过子查询把FILM_PRODUKCE和OSOBA的关联结果去重,再进行聚合:
SELECT f.NAZEV, f.VYDANI, f.DELKA, f.CENA, LISTAGG(p.JMENO, ',') WITHIN GROUP (ORDER BY p.JMENO) AS Produkce FROM FILM_PRODEJNA fp INNER JOIN FILM f ON fp.FILM_ID_FILM = f.ID_FILM LEFT JOIN ( -- 子查询先获取每部电影对应的唯一姓名 SELECT DISTINCT fp2.FILM_ID_FILM, o.JMENO FROM FILM_PRODUKCE fp2 JOIN OSOBA o ON fp2.OSOBA_ID_OSOBA = o.ID_OSOBA -- 补全关联条件 ) p ON p.FILM_ID_FILM = f.ID_FILM GROUP BY f.NAZEV, f.VYDANI, f.DELKA, f.CENA;
额外注意点
- 确保你的
GROUP BY子句包含了所有非聚合字段(也就是SELECT里除了LISTAGG之外的所有字段),避免分组逻辑错误。 - 如果
FILM表的NAZEV(电影名)不是唯一标识,建议改用FILM.ID_FILM作为分组依据之一,避免不同电影因为同名被错误合并。
内容的提问来源于stack exchange,提问作者Jakub Stanek
相关产品推荐
相关产品推荐

