sql >> Databasteknik >  >> RDS >> PostgreSQL

SQL Hitta alla direkta ättlingar i ett träd

I nya PostgreSQL 8.4 du kan göra 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 den här artikeln i min blogg för mer information:

I 8.3 eller tidigare måste du skriva 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';

och välj från denna funktion:

SELECT  *
FROM    fn_hierarchy_connect_by(4, 1)

Den första parametern är roten id , den andra ska vara 1 .

Se den här artikeln i min blogg för mer information:

Uppdatering:

Om du bara vill visa underordnade nivåer på första nivån, eller själva noden om underordnade inte finns, ställer du den här frågan:

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
        )

Detta är mer effektivt än en JOIN , eftersom den andra frågan tar högst två indexsökningar:den första för att se till att ta reda på om ett underordnat finns, den andra för att välja den överordnade raden om det inte finns några underordnade.



  1. Hur byter man ut OR-operatör med UNION-operatör?

  2. Hur löser jag ORA-12516-felet?

  3. MySQL CAST som DATUM

  4. Vad är nytt i PostgreSQL 11