【问题标题】:Recursive CTE using inner join in SQL在 SQL 中使用内连接的递归 CTE
【发布时间】:2020-04-11 03:54:15
【问题描述】:

我必须制作一个递归 CTE 以将所有知道 kevin bacon 的演员还给我,以便更好地了解我的数据库只通过两个演员得到一个知道培根的人 例如,您可能想知道 Alfred Hitchcock 如何与 Kevin Bacon 联系起来。一个答案是: 阿尔弗雷德·希区柯克和奥森·威尔斯在战争中的演艺事业(1943 年),和 奥森威尔斯和杰克尼科尔森在一个安全的地方(1971),和 杰克尼科尔森和凯文培根一起出演了几个好男人(1992)! 我正在尝试两种不同的方法,一种是给我一个空集,另一种是给我这个错误消息'递归通用表表达式的完整选择 数据库管理员。 BACON" 必须是两个或多个全选的 UNION 链接 并且不得包含列函数、子句 GROUP BY、HAVING 或 ORDER BY 仍包含带有 CLAUSE ON 的显式连接。'

WITH bacon (actorid, bacon_number) AS (
SELECT UNIQUE actorid, 0 FROM movies2actors 
        WHERE actorid =  (SELECT actorid FROM actors WHERE name = 'Bacon, Kevin (I)') UNION ALL
SELECT movies2actors.actorid, bacon.bacon_number + 1
FROM movies2actors, bacon 
       WHERE movies2actors.actorid IN 
            (SELECT UNIQUE actorid FROM movies2actors WHERE movieid IN (SELECT UNIQUE movieid FROM movies2actors 
                WHERE actorid = (SELECT actorid FROM actors WHERE name = 'Bacon, Kevin (I)') )) 
            AND movies2actors.actorid <> (SELECT actorid FROM actors WHERE name = 'Bacon, Kevin (I)') AND bacon.bacon_number<2  
)
SELECT bacon.actorid , bacon.bacon_number  FROM bacon ;

WITH bacon (actorid,relationid, bacon_number) AS (
SELECT UNIQUE actorid, actorid ,0 FROM ACTORS 
        WHERE name = 'Bacon, Kevin (I)'
UNION ALL
SELECT ACTORS.actorid,bacon.relationid, bacon.bacon_number + 1
FROM ACTORS
       JOIN  bacon ON ACTORS.actorid = bacon.relationid
       WHERE ACTORS.actorid IN 
            (SELECT UNIQUE actorid FROM movies2actors WHERE movieid IN (SELECT UNIQUE movieid FROM movies2actors 
                WHERE actorid = (SELECT actorid FROM actors WHERE name = 'Bacon, Kevin (I)') )) 
            AND ACTORS.actorid <> (SELECT actorid FROM actors WHERE name = 'Bacon, Kevin (I)') AND bacon.bacon_number<2     
)
SELECT bacon.actorid , bacon.bacon_number  FROM bacon ;

【问题讨论】:

    标签: sql recursion join db2 recursive-cte


    【解决方案1】:

    在递归 CTE 中使用旧的连接语法(在 Db2 LUW 中)

    table a,
    table b
    Where a.col = b.col 
    

    【讨论】:

      【解决方案2】:

      试试这个:

      /*
      WITH 
        Movies (movieid, moviename) AS 
      (
       VALUES
         (1, 'Show Business at War (1943)')
       , (2, 'A Safe Place (1971)')
       , (3, 'A Few Good Men (1992)')
      )
      , Actors (actorid, actorname) AS 
       (
       VALUES
         (1, 'Alfred Hitchcock')
       , (2, 'Orson Welles')
       , (3, 'Jack Nicholson')
       , (4, 'Kevin Bacon')
       )
       , Movies2Actors (movieid, actorid) AS
       (
       VALUES
        (1, 1)
      , (1, 2)   
      , (2, 2)   
      , (2, 3)   
      , (3, 3)
      , (3, 4)
       )
      , 
      */
      bacon (actorid, level, chain) AS
      (
      SELECT mo.actorid, 1, cast('|'||trim(a.actorid)||'|'||trim(mo.actorid)||'|' AS varchar(1000))
      FROM Actors a, Movies2Actors mb, Movies2Actors mo
      WHERE a.actorname=
      'Kevin Bacon' 
      --'Jack Nicholson'
      --'Orson Welles'
      AND a.actorid=mb.actorid AND mb.movieid=mo.movieid
      AND a.actorid<>mo.actorid 
        UNION ALL
      SELECT mo.actorid, b.level+1, b.chain||trim(mo.actorid)||'|'
      FROM bacon b, Movies2Actors mb, Movies2Actors mo
      WHERE b.actorid=mb.actorid AND mb.movieid=mo.movieid
      AND locate('|'||trim(mo.actorid)||'|', b.chain)=0 
      )
      SELECT DISTINCT a.actorname
      --, b.*
      FROM bacon b
      JOIN Actors a ON a.actorid=b.actorid;
      

      您可以取消注释带有示例数据的注释块并按原样运行语句以检查结果。
      chain 列是为了防止递归。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-18
        相关资源
        最近更新 更多