sql >> データベース >  >> RDS >> PostgreSQL

推移閉包に使用される再帰クエリ

    いくつかの場所で簡略化できます( acct_id を想定) およびparent_id NOT NULLです ):

    WITH RECURSIVE search_graph AS (
       SELECT parent_id, ARRAY[acct_id] AS path
       FROM   account
    
       UNION  ALL
       SELECT g.parent_id, sg.path || g.acct_id
       FROM   search_graph sg
       JOIN   account g ON g.acct_id = sg.parent_id 
       WHERE  g.acct_id <> ALL(sg.path)
       )
    SELECT path[1] AS child
         , path[array_upper(path,1)] AS parent
         , path
    FROM   search_graph
    ORDER  BY path;
    
    • acct_id深さ cycle クエリの単なるノイズです。
    • WHERE 条件は、1ステップ前、に再帰を終了する必要があります 最上位ノードからの重複エントリが結果に含まれます。それはあなたのオリジナルでは「1つずつ」でした。

    残りはフォーマットです。

    知っている グラフで可能な唯一の円は自己参照です。これを安くすることができます:

    WITH RECURSIVE search_graph AS (
       SELECT parent_id, ARRAY[acct_id] AS path, acct_id <> parent_id AS keep_going
       FROM   account
    
       UNION  ALL
       SELECT g.parent_id, sg.path || g.acct_id, g.acct_id <> g.parent_id
       FROM   search_graph sg
       JOIN   account g ON g.acct_id = sg.parent_id 
       WHERE  sg.keep_going
    )
    SELECT path[1] AS child
         , path[array_upper(path,1)] AS parent
         , path
    FROM   search_graph
    ORDER  BY path;
    

    SQLフィドル。

    修飾子( varchar(5)など)を使用したデータ型には問題(少なくともpg v9.4まで)があることに注意してください。 )配列の連結は修飾子を失いますが、rCTEは正確に一致する型を要求するため:

    • 型修飾子を使用したデータ型の驚くべき結果


    1. SQLite-関係を作成する

    2. MySQLの階層クエリ

    3. jdbcTimestampまたはDateを使用する場合のOracleとの無視できない実行プランの違い

    4. Oracle DB:大文字と小文字を区別せずにクエリを作成するにはどうすればよいですか?