Oracle SQL listagg在一列中包含多个列

时间:2018-03-30 22:24:34

标签: sql oracle

我有以下db with query和result image 但正如你所看到的那样多次返回相同的名字它应该看起来像Rob,Rose,Will就是这样。我该怎么做才能达到这个目标?我的查询有什么问题吗?

SELECT FILM.NAZEV, FILM.VYDANI, FILM.DELKA, FILM.CENA, LISTAGG(OSOBA.JMENO, ',') WITHIN GROUP (ORDER BY OSOBA.JMENO) AS ProdukceFROM 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 PRODUKCE ON PRODUKCE.ID_PRODUKCE = FILM_PRODUKCE.ID_FILM_PRODUKCE
LEFT JOIN ZASTOUPENI ON ZASTOUPENI.ID_ZASTOUPENI = PRODUKCE.ID_PRODUKCE
LEFT JOIN OSOBA ON ZASTOUPENI.OSOBA_ID_OSOBA = OSOBA.ID_OSOBA GROUP BY FILM.NAZEV, FILM.VYDANI, FILM.DELKA, FILM.CENA;

2 个答案:

答案 0 :(得分:1)

难点在于您的查询返回了重复的名称。遗憾的是,您无法将DISTINCTLISTAGG()一起使用。所以你必须做以下事情:

SELECT nazev, vydani, delka, cena
     , LISTAGG(jmeno, ',') WITHIN GROUP (ORDER BY jmeno) AS Produkce
  FROM (
    SELECT DISTINCT FILM.NAZEV, FILM.VYDANI, FILM.DELKA, FILM.CENA, OSOBA.JMENO
      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 PRODUKCE ON PRODUKCE.ID_PRODUKCE = FILM_PRODUKCE.ID_FILM_PRODUKCE
      LEFT JOIN ZASTOUPENI ON ZASTOUPENI.ID_ZASTOUPENI = PRODUKCE.ID_PRODUKCE
      LEFT JOIN OSOBA ON ZASTOUPENI.OSOBA_ID_OSOBA = OSOBA.ID_OSOBA
) GROUP BY nazev, vydani, delka, cena;

基本上,我接受了您的查询,添加了DISTINCT,并将其用作LISTAGG()等的子查询。但我认为包含此表FILM_PRODEJNA是您真正的问题。每部电影有多个prodejny(我希望我有这个权利),对吗?但你只想找到至少有一个prodejna的电影?在这种情况下,我建议使用EXISTS而不是INNER JOIN。当然可能仍然有重复,我不知道你的表之间的确切关系:

SELECT FILM.NAZEV, FILM.VYDANI, FILM.DELKA, FILM.CENA
     , LISTAGG(OSOBA.JMENO, ',') WITHIN GROUP ( ORDER BY OSOBA.JMENO )
  FROM FILM
  LEFT JOIN FILM_PRODUKCE
    ON FILM_PRODUKCE.FILM_ID_FILM = FILM.ID_FILM
  LEFT JOIN PRODUKCE
    ON PRODUKCE.ID_PRODUKCE = FILM_PRODUKCE.ID_FILM_PRODUKCE
  LEFT JOIN ZASTOUPENI
    ON ZASTOUPENI.ID_ZASTOUPENI = PRODUKCE.ID_PRODUKCE
  LEFT JOIN OSOBA
    ON ZASTOUPENI.OSOBA_ID_OSOBA = OSOBA.ID_OSOBA
 WHERE EXISTS ( SELECT 1 FROM FILM_PRODEJNA
                 WHERE FILM_PRODEJNA.FILM_ID_FILM = FILM.ID_FILM )
 GROUP BY FILM.NAZEV, FILM.VYDANI, FILM.DELKA, FILM.CENA;

如果我可以发表评论,如果您使用表别名,则可以省去一些打字 - 例如,您不需要反复键入ZASTOUPENI

答案 1 :(得分:0)

有多个记录会导致listagg函数出现重复。解决问题的最佳方法是找到导致重复的数据。但是如果你想采用一种更短的方法来修复它并牺牲效率,你可以做一个子查询并在你需要的所有列上选择distinct,然后执行listagg group by。见下文。

System.out.println(script.replaceAll("\\b.*?a\\b", "$0r"));