sql >> Database teknologi >  >> RDS >> PostgreSQL

SQL Find alle direkte efterkommere i et træ

I den nye PostgreSQL 8.4 du kan gøre det med en 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

Se denne artikel i min blog for detaljer:

I 8.3 eller tidligere, skal du skrive en funktion:

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';

og vælg fra denne funktion:

SELECT  *
FROM    fn_hierarchy_connect_by(4, 1)

Den første parameter er roden id , den anden skal være 1 .

Se denne artikel i min blog for flere detaljer:

Opdatering:

For kun at vise børn på første niveau eller selve noden, hvis børnene ikke findes, skal du udsende denne forespørgsel:

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
        )

Dette er mere effektivt end en JOIN , da den anden forespørgsel højst tager to indeksscanninger:den første for at sikre at finde ud af, om der findes et underordnet, den anden for at vælge den overordnede række, hvis der ikke findes nogen underordnede.



  1. Odd IntegrityError på MySQL:#1452

  2. Konverter forespørgsel fra MySql til Sqlite

  3. hvordan man beregner lighed mellem to strenge i MYSQL

  4. Slet en Crashed Innodb-tabel