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

再帰CTEで重複アイテムを検出する

    depという単語 2番目のクエリ(unionの後) )があいまいです。実際には、rdepsの列として解釈されます。 、objectdependencies.

    with recursive rdeps as (
      select dep
      from objectdependencies dep
      where dep.dependson = 4 -- starting point
      union all
      select dep -- this means r.dep
      from objectdependencies dep
      join rdeps r
        on (r.dep).id = dep.dependson
    ) select (dep).id from rdeps;
    

    これが、クエリが無限のループを作成する理由です。エイリアスを変更することでこれを修正できます:

    with recursive rdeps as (
      select dep
      from objectdependencies dep
      where dep.dependson = 4 -- starting point
      union all
      select objectdep
      from objectdependencies objectdep
      join rdeps r
        on (r.dep).id = objectdep.dependson
    ) select (dep).id from rdeps;
    
     id 
    ----
      1
      2
      3
      1
      2
      1
    (6 rows)    
    

    または、より良いのは、善良な主が意図したように、列を使用するだけです。

    with recursive rdeps as (
        select id, dependson
        from objectdependencies
        where dependson = 4
    union all
        select d.id, d.dependson
        from objectdependencies d
        join rdeps r
        on r.id = d.dependson
    ) 
    select *
    from rdeps;
    

    質問の最初のクエリは、再帰クエリによって生成された異なる(並列)ブランチ間の通信がないため、プレーンSQLで実行できるすべてです。機能的なアプローチでは、すべてのブランチに共通のストアとして一時テーブルを使用できます。関数は次のようになります:

    create or replace function rec_function(int)
    returns void language plpgsql as $$
    declare
        i int;
    begin
        for i in
            select id
            from objectdependencies
            where dependson = $1
        loop
            if not exists(
                select from temp_table 
                where id = i)
            then
                insert into temp_table values(i);
                perform rec_function(i);
            end if;
        end loop;
    end $$;
    

    使用法:

    create temp table temp_table(id int);
    
    select rec_function(4);
    
    select *
    from temp_table;
    


    1. Oracleでの時間のない日付タイプ

    2. SQLServerデータベースの既存のテーブルに列を追加する

    3. OracleIN句でのLIKEの使用

    4. Oracle 11gで2つの日付の間の日数を取得するにはどうすればよいですか?