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

自分自身を参照するpostgresqlテーブルで、指定されたIDから始まるすべてのIDを再帰的に取得するにはどうすればよいですか?

    再帰共通テーブル式 を使用します 。常にルートから開始し、IDの配列を使用して、特定のidのパスを取得します WHERE 条項。

    id = 1の場合 :

    with recursive cte(id, parent, name, ids) as (
        select id, parent, name, array[id]
        from my_table
        where parent is null
    union all
        select t.id, t.parent, concat(c.name, t.name, '/'), ids || t.id
        from cte c
        join my_table t on c.id = t.parent
    )
    select id, name 
    from cte
    where 1 = any(ids) and id <> 1
    
     id |         name          
    ----+-----------------------
      2 | /home/
      5 | /usr/
      6 | /usr/local/
      3 | /home/user/
      4 | /home/user/bin/
    (5 rows)
    

    id = 2の場合 :

    with recursive cte(id, parent, name, ids) as (
        select id, parent, name, array[id]
        from my_table
        where parent is null
    union all
        select t.id, t.parent, concat(c.name, t.name, '/'), ids || t.id
        from cte c
        join my_table t on c.id = t.parent
    )
    select id, name 
    from cte
    where 2 = any(ids) and id <> 2
    
     id |         name          
    ----+-----------------------
      3 | /home/user/
      4 | /home/user/bin/
    (2 rows)    
    

    双方向クエリ

    質問は本当に面白いです。上記のクエリはうまく機能しますが、リーフを要求している場合でもすべてのツリーノードを解析するため非効率的です。より強力なソリューションは、双方向再帰クエリです。内側のクエリは特定のノードから上に移動し、外側のクエリはノードから下に移動します。

    with recursive outer_query(id, parent, name) as (
        with recursive inner_query(qid, id, parent, name) as (
            select id, id, parent, name
            from my_table
            where id = 2        -- parameter
        union all
            select qid, t.id, t.parent, concat(t.name, '/', q.name)
            from inner_query q
            join my_table t on q.parent = t.id
        )
        select qid, null::int, right(name, -1)
        from inner_query
        where parent is null
    union all
        select t.id, t.parent, concat(q.name, '/', t.name)
        from outer_query q
        join my_table t on q.id = t.parent
    )
    select id, name
    from outer_query
    where id <> 2;          -- parameter
    



    1. MountainLionにMySQLdbをインストールする方法

    2. 世論機関のデータモデル

    3. MySQL:複数の行をgroup_concatすることは可能ですか?

    4. C#用のmysql.data.dllはどこにありますか