Postgreツリー構造の追加、削除、変更、クエリ、再帰クエリWITH RECURSIVE

1.はじめに

階層関係がある場合、通常、親ノードを示すようにテーブル構造を設計するときに、parent_idフィールドが追加されます。

ツリーテーブルのクエリは通常のテーブルとは異なります。ほとんどの場合、親ノードのデータをクエリすると、その子ノードに再帰的にクエリを実行する必要があります。また、親ノードを削除すると、子ノードも再帰的に削除する必要があります。

SQLステートメントの制限により、関数またはストアドプロシージャでない限り、再帰ステートメントを直接記述することはできません。

POSTGREデータベースエンジンは、上記の問題を解決するためにWITHRECURSIVEを提供します。

詳細については、公式情報を参照してください:https://www.postgresql.org/docs/current/queries-with.html

たとえば、次のツリー構造:

 

 

二、WITH

WITHは、より大きなクエリで使用するための補助ステートメントを作成する方法を提供します。

これらのステートメントは通常、共通テーブル式(commontableexpression)またはcteと呼ばれます。

これは、1つのクエリに対してのみ存在する一時テーブルを定義するものと考えることができます。

WITH句の各補助ステートメントは、SELECT、INSERT、UPDATE、またはDELETEにすることができます。

WITH句自体がメインステートメントに付加されます。メインステートメントは、SELECT、INSERT、UPDATE、またはDELETEにすることもできます。

たとえば、次のSQLステートメント: 

 

T as(
    select * from template_info where parent_id = -1 
)select * from T

 

すべての第1レベルのノードが照会され、括弧内のステートメントによって検出された内容が一時テーブルTに格納されてから、すべてがTから照会されます。

複数のWITH句をコンマで区切って定義できるため、複数のテーブルをクエリし、並行してクエリを実行してから、一時テーブルのコレクションをクエリできます。

 

 

 

3、リカーシブ

オプションのRECURSIVE再帰修飾子は、単純な構文から、標準SQLでは不可能なことを実行できる機能に変更されました。

再帰を使用すると、WITHクエリは独自の出力を参照できます。

with RECURSIVE t as 
        (select * from template_info where id = 18 
         union all 
         (selectd。* from t inner join template_info d on t.id = d.parent_id)
        )select * from t

クエリのロジックは次のとおりです。

1.非再帰的な項目を計算します。つまり、select * from template_info where id = 18です。この行はルートノードを見つけ、その結果を一時テーブルBに格納します。

2.再帰項を計算します。つまり、t.id = d.parent_idのt内部結合template_infodからd。*を選択し、一時テーブルBとtemplate_infoを結合してCを取得し、BCをマージしてDを取得します。

3.すべてのCが空になるまで再帰項目を計算し、結果セットをマージして、反復プロセスを終了します。

4.結果セットをクエリして、最終結果を取得します。

注:厳密に言えば、このプロセスは再帰的ではなく反復的ですが、再帰はSQL標準委員会によって選択された用語です。

 

 さらに分解する手順:

1.クエリ1

 select * from template_info where id = 18

 

 2.合併

    with RECURSIVE t as 
        (select * from template_info where id = 18 
         union 
         (selectd。* from t inner join template_info d on t.id = d.parent_id where t.id = 18)
        )select * from t

 

 3.再マージ

コードをコピーする

    with RECURSIVE t as 
        (select * from template_info where id = 18 
         union 
         (selectd。* from t inner join template_info d on t.id = d.parent_id where t.id = 18)
        )select * from t union(
            with RECURSIVE t2 as 
         (selectd。* from t inner join template_info d on t.id = d.parent_id where t.id = 19)
        )select * from t2 

コードをコピーする

 

4.再度マージします。これ以上、クエリを終了しません。

コードをコピーする

    with RECURSIVE t as 
        (select * from template_info where id = 18 
         union 
         (selectd。* from t inner join template_info d on t.id = d.parent_id where t.id = 18)
        )select * from t union(
            with RECURSIVE t2 as 
         (selectd。* from t inner join template_info d on t.id = d.parent_id where t.id = 20)
        )select * from t2 

コードをコピーする

 

 

 第四に、WITH更新中

WITH t AS(
    UPDATE製品SET価格=価格* 1.05
    返品* 
SELECT * FROM t;

5、WITHでのDELETEとINSERT

このクエリは実際にproductsは行からに移動しますproducts_logからの指定された行WITHDELETE削除products

RETURNING句でコンテンツ返すと、メインクエリが出力を読み取り、挿入しproducts_logます。

 

コードをコピーする

WITHmoved_rows AS(
    DELETE FROM products 
    WHERE 
        "date"> = '2010-10-01' AND 
        "date" <'2010-11-01' 
    RETURNING * 
INSERT INTO products_log 
SELECT * FROMmoved_rows;

コードをコピーする

 

 

 

おすすめ

転載: blog.csdn.net/u014556081/article/details/113185656
おすすめ