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

PostgreSQLは再帰CTEから関数にデータを渡します

    一番下から始めると、パスの検索をより効率的にすることができます。子供たちから始めましょう。親から始める場合、それはすべての子供を横断することを伴います。一方、子から検索した場合、親は1つしかないため、ソースとターゲットの間のパスを見つけるのに時間を無駄にすることはありません。

    with recursive find_parent(source, target, recentness) as
    (
        select source, target, 0 
        from tbl
        where target = 9
    
        union all
    
        select i.source, i.target, fp.recentness + 1
        from tbl i
        join find_parent fp on i.target = fp.source
    ),
    construct_path(source, target, recentness, path) as
    (
      select source, target, recentness, source || '.' || target
      from find_parent 
      where recentness = (select max(recentness) from find_parent)
    
      union
    
      select dd.source, dd.target, dd.recentness, cp.path || '.' || dd.target
      from find_parent dd
      join construct_path cp on dd.recentness = cp.recentness - 1  
    )
    select source, target, path 
    from construct_path
    order by recentness desc
    

    出力:

    SOURCE   TARGET   PATH
    1        2        1.2
    2        4        1.2.4
    4        9        1.2.4.9
    

    ライブテスト:http://www.sqlfiddle.com/#!1 / 13e6b / 1

    これに似ています:SQLSERVER2005で親に子を与える方法

    これは最適化されており、特定のもの(ソース)がすでに見つかっている場合は、親への再帰をカットします。

    ソース=2

    ターゲット=9

    with recursive find_parent(source, target, recentness) as
    (
        select source, target, 0 
        from tbl
        where target = 9
    
        union all
    
        select i.source, i.target, fp.recentness + 1
        from tbl i
        join find_parent fp on i.target = fp.source 
             -- despite the name, this target is another one's source
             and i.target <> 2
    )
    ,construct_path(source, target, recentness, path) as
    (
        select source, target, recentness, source || '.' || target
        from find_parent 
        where recentness = (select max(recentness) from find_parent)
    
        union
    
        select dd.source, dd.target, dd.recentness, cp.path || '.' || dd.target
        from find_parent dd
        join construct_path cp on dd.recentness = cp.recentness - 1  
    
    )
    select source, target, path
    from construct_path
    order by recentness desc
    

    出力:

    SOURCE   TARGET  PATH
    2        4       2.4
    4        9       2.4.9
    

    ライブテスト:http://www.sqlfiddle.com/#!1 / 13e6b / 16



    1. GROUPBY句のないMySQL集計関数

    2. SQL ServerでのDB_NAME()のしくみ

    3. PostgreSQL監査ログのベストプラクティス

    4. PostgreSQLで自動インクリメント主キーを定義する方法