sql >> Databáze >  >> RDS >> PostgreSQL

SQL Najít všechny přímé potomky ve stromu

V novém PostgreSQL 8.4 můžete to udělat pomocí 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

Podrobnosti najdete v tomto článku na mém blogu:

V 8.3 nebo dříve, budete muset napsat funkci:

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

a vyberte z této funkce:

SELECT  *
FROM    fn_hierarchy_connect_by(4, 1)

Prvním parametrem je kořen id , druhý by měl být 1 .

Další podrobnosti najdete v tomto článku na mém blogu:

Aktualizace:

Chcete-li zobrazit pouze podřízené položky první úrovně nebo samotný uzel, pokud podřízené položky neexistují, zadejte tento dotaz:

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
        )

To je efektivnější než JOIN , protože druhý dotaz zabere maximálně dvě prohledávání indexu:první, aby se ujistil, že existuje podřízený objekt, druhý pro výběr nadřazeného řádku, pokud žádné podřízené položky neexistují.



  1. Ekvivalent GROUP_CONCAT v Django

  2. Nelze použít název tabulky PL/SQL jako proměnnou v proceduře PL/SQL?

  3. Chci znovu použít mezery smazaných řádků

  4. Jak rychle přetřídit tabulku MySQL podle jednoho ze sloupců?