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

SQLツリー内のすべての直接の子孫を検索します

    新しいPostgreSQL 8.4では CTEでそれを行うことができます :

    WITH RECURSIVE q AS
            (
            SELECT  h, 1 AS level, ARRAY[id] AS breadcrumb
            FROM    t_hierarchy h
            WHERE   parent = 0
            UNION ALL
            SELECT  hi, q.level + 1 AS level, breadcrumb || id
            FROM    q
            JOIN    t_hierarchy hi
            ON      hi.parent = (q.h).id
            )
    SELECT  REPEAT('  ', level) || (q.h).id,
            (q.h).parent,
            (q.h).value,
            level,
            breadcrumb::VARCHAR AS path
    FROM    q
    ORDER BY
            breadcrumb
    

    詳細については、私のブログのこの記事を参照してください:

    8.3で 以前は、関数を作成する必要があります:

    CREATE TYPE tp_hierarchy AS (node t_hierarchy, level INT);
    
    CREATE OR REPLACE FUNCTION fn_hierarchy_connect_by(INT, INT)
    RETURNS SETOF tp_hierarchy
    AS
    $$
            SELECT  CASE
                    WHEN node = 1 THEN
                            (t_hierarchy, $2)::tp_hierarchy
                    ELSE
                            fn_hierarchy_connect_by((q.t_hierarchy).id, $2 + 1)
                    END
            FROM    (
                    SELECT  t_hierarchy, node
                    FROM    (
                            SELECT  1 AS node
                            UNION ALL
                            SELECT  2
                            ) nodes,
                            t_hierarchy
                    WHERE   parent = $1
                    ORDER BY
                            id, node
                    ) q;
    $$
    LANGUAGE 'sql';
    

    この機能から選択します:

    SELECT  *
    FROM    fn_hierarchy_connect_by(4, 1)
    

    最初のパラメータはルートidです 、2番目は1である必要があります 。

    詳細については、私のブログのこの記事を参照してください:

    更新:

    第1レベルの子のみ、または子が存在しない場合はノード自体を表示するには、次のクエリを発行します。

    SELECT  *
    FROM    t_hierarchy
    WHERE   parent = @start
    UNION ALL
    SELECT  *
    FROM    t_hierarchy
    WHERE   id = @start
            AND NOT EXISTS
            (
            SELECT  NULL
            FROM    t_hierarchy
            WHERE   parent = @start
            )
    

    これは、JOINよりも効率的です 、2番目のクエリは最大で2回のインデックススキャンを実行するため、最初のクエリは子が存在するかどうかを確認し、2番目のクエリは子が存在しない場合は親行を選択します。



    1. MyISAMとInnoDBのインデックス使用法におけるmysqlの違い

    2. Postgresql。 CREATECAST'文字が'から'整数'に変化します

    3. Geonamesデータベース:1つのmysqlクエリのみで完全な階層(国-> admin1-> admin2->都市)を取得する

    4. 警告:このページのフォームには1000を超えるフィールドがありますPHP MySql