LISTAGG 中的 LISTAGG

问题描述 投票:0回答:1

我使用一些在线转换器将MySQL中的视图转换为oracle,结果是这样的:

CREATE  VIEW actor_info
AS
SELECT
a.actor_id,
a.first_name,
a.last_name,
GROUP_CONCAT(DISTINCT ||(c.name, ': ',
        (SELECT GROUP_CONCAT(f.title FROM dual ORDER BY f.title SEPARATOR FROM dual ', ')
                    FROM film f
                    INNER JOIN film_category fc
                      ON f.film_id = fc.film_id
                    INNER JOIN film_actor fa
                      ON f.film_id = fa.film_id
                    WHERE fc.category_id = c.category_id
                    AND fa.actor_id = a.actor_id
                 )
             )
             ORDER BY c.name SEPARATOR '; ')
AS film_info
FROM actor a
LEFT JOIN film_actor fa
  ON a.actor_id = fa.actor_id
LEFT JOIN film_category fc
  ON fa.film_id = fc.film_id
LEFT JOIN category c
  ON fc.category_id = c.category_id
GROUP BY a.actor_id, a.first_name, a.last_name;

转换器转换得不太好,所以我不得不修改查询并最终得到如下结果:

    CREATE  VIEW actor_info
AS
SELECT
a.actor_id,
a.first_name,
LISTAGG(c.name || ': ',
        (SELECT LISTAGG(f.title, ', ') within group (order by f.title)
                    FROM film f
                    INNER JOIN film_category fc
                      ON f.film_id = fc.film_id
                    INNER JOIN film_actor fa
                      ON f.film_id = fa.film_id
                    WHERE fc.category_id = c.category_id
                    AND fa.actor_id = a.actor_id
                 ) 
             ) WITHIN group (order by c.name)
AS film_info
FROM actor a
LEFT JOIN film_actor fa
  ON a.actor_id = fa.actor_id
LEFT JOIN film_category fc
  ON fa.film_id = fc.film_id
LEFT JOIN category c
  ON fc.category_id = c.category_id
GROUP BY a.actor_id, a.first_name, a.last_name, c.name;

但是我仍然收到多个错误,例如我无法在第一个

distinct
或那个
listagg
中使用
argument should be a constant or a function of expression in GROUP BY
。我没有办法尝试解决这个问题,对于错误是什么或执行此视图的其他方法有什么建议吗?

oracle-database
1个回答
0
投票

Oracle的

listagg()
内部不支持distinct,这有点蛋疼。您遇到的另一个错误 ORA-30497 是因为您不小心让第二个
listagg()
调用了第一个的分隔符。

如果没有样本数据和预期结果,有点难以判断,但看起来您正在寻找类似的东西:

SELECT a.actor_id, a.first_name, a.last_name,
  LISTAGG(c.name || ': ' || (
    SELECT LISTAGG(f.title, ', ') WITHIN GROUP (ORDER BY f.title)
    FROM film f
    INNER JOIN film_actor fa
    ON fa.film_id = f.film_id
    INNER JOIN film_category fc
    ON f.film_id = fc.film_id
    WHERE fc.category_id = c.category_id -- from main query
    AND fa.actor_id = a.actor_id -- from main query
), '; ') WITHIN GROUP (ORDER BY c.name)
AS film_info
FROM actor a
LEFT JOIN (
  SELECT DISTINCT fa.actor_id, c.category_id, c.name
  FROM film_actor fa
  LEFT JOIN film_category fc
    ON fc.film_id = fa.film_id
  LEFT JOIN category c
  ON c.category_id = fc.category_id
) c
ON c.actor_id = a.actor_id
GROUP BY a.actor_id, a.first_name, a.last_name;

“独特”部分是通过内联视图实现的,而内部

listagg
只需要找到该类别/演员的所有电影。

© www.soinside.com 2019 - 2024. All rights reserved.