PostgreSQL
 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 , второто трябва да е 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 , тъй като втората заявка ще отнеме най-много две сканирания на индекс:първото, за да се увери, че съществува дъщерен елемент, второто, за да избере родителския ред, ако не съществуват дъщерни елементи.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да получите достъп до процедурата, която връща setof refcursor от PostgreSQL в Java?

  2. Как да предам параметър към sql 'in' израз?

  3. Итерация над integer[] в PL/pgSQL

  4. Приложение Simple Rails:Грешка Не може да се посети Integer

  5. PHP не зарежда php_pgsql.dll в Windows