Postgre tree structure addition, deletion, modification, query, recursive query WITH RECURSIVE

1. Introduction

When there is a hierarchical relationship, the parent_id field is usually added when designing the table structure to indicate the parent node.

The query of the tree table is different from the regular table. In most cases, querying the data of the parent node must recursively query its child nodes, and deleting the parent node will also recursively delete the child nodes.

Due to the limitations of SQL statements, it is impossible to write recursive statements directly, unless it is a function or stored procedure.

POSTGRE database engine provides WITH RECURSIVE to solve the above problems.

For details, please refer to official information: https://www.postgresql.org/docs/current/queries-with.html

For example, the following tree structure:

 

 

二、WITH

WITH provides a way to write auxiliary statements for use in larger queries.

These statements are usually called common table expressions (commontableexpression) or cte,

It can be thought of as defining a temporary table that exists only for one query.

Each auxiliary statement in the WITH clause can be SELECT, INSERT, UPDATE or DELETE;

The WITH clause itself is attached to the main statement, which can also be SELECT, INSERT, UPDATE, or DELETE.

For example, the following SQL statement: 

 

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

 

All the first-level nodes are queried, and the contents detected by the statement in parentheses are stored in the temporary table T, and then all are queried from T.

You can define multiple WITH clauses, separated by commas, so that you can query multiple tables, query in parallel, and then query the collection of temporary tables.

 

 

 

Three, RECURSIVE

The optional RECURSIVE recursive modifier has been changed from a simple syntax to a feature that can accomplish things that are impossible in standard SQL.

Using recursion, WITH queries can refer to their own output.

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

The logic of the query is:

1. Calculate non-recursive items, that is, select * from template_info where id =18. This row finds out the root node and stores the result in temporary table B;

2. Calculate the recursive term, that is, select d.* from t inner join template_info d on t.id=d.parent_id, join the temporary table B and template_info to obtain C, and merge BC to obtain D;

3. Keep calculating the recursive items and merging the result sets until all C is empty, ending the iteration process;

4. Query the result set to get the final result.

Note: Strictly speaking, this process is iterative rather than recursive, but recursion is the term chosen by the SQL Standards Committee.

 

 Steps to further disassemble:

1. Query one

 select * from template_info where id =18

 

 2. Merger

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

 

 3. Remerge

Copy code

    with RECURSIVE t as 
        (select * from template_info where id =18
         union 
         (select d.* 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 
        (
         (select d.* from t inner join template_info d on t.id=d.parent_id where t.id=19)
        ) select * from t2
        ) 

Copy code

 

4. Merge again, no more, end the query.

Copy code

    with RECURSIVE t as 
        (select * from template_info where id =18
         union 
         (select d.* 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 
        (
         (select d.* from t inner join template_info d on t.id=d.parent_id where t.id=20)
        ) select * from t2
        ) 

Copy code

 

 

 Fourth, WITHmid-UPDATE

WITH t AS (
    UPDATE products SET price = price * 1.05
    RETURNING *
)
SELECT * FROM t;

Five, DELETE and INSERT in WITH

This query actually productsmoves from the row to products_log. WITHThe DELETEdelete productsin the specified line from,

RETURNINGReturn their content in its clauses, and then the main query reads the output and inserts it products_log.

 

Copy code

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

Copy code

 

 

 

Guess you like

Origin blog.csdn.net/u014556081/article/details/113185656