2010-07-22 20 views
12

Potrzebuję pomocy z zapytaniem cyklicznym. Zakładając poniższej tabeli:Rekurencyjny PostgreSQL z

CREATE TEMPORARY TABLE tree (
    id  integer PRIMARY KEY, 
    parent_id integer NOT NULL, 
    name  varchar(50) 
);  

INSERT INTO tree (id, parent_id, name) VALUES (3, 0, 'Peter'), (2,0, 'Thomas'), (5,2, 'David'), (1, 0, 'Rob'), (8, 0, 'Brian'); 

mogę pobrać listę wszystkich ludzi i ich dzieci z następującym zapytaniem:

WITH RECURSIVE recursetree(id, parent_id) AS (
    SELECT id, parent_id FROM tree WHERE parent_id = 0 
    UNION 
    SELECT t.id, t.parent_id 
    FROM tree t 
    JOIN recursetree rt ON rt.id = t.parent_id 
) 
SELECT * FROM recursetree; 

Jak mogę wymienić je w kolejności, a także sortować elementy pierwszego stopnia wg nazwy? Na przykład, sygnał wyjściowy będzie:

id, parent_id, name  
8, 0, "Brian" 
3, 0, "Peter" 
1, 0; "Rob" 
2, 0, "Thomas" 
5, 2, " David" 

Dzięki

** EDIT. Należy pamiętać, że dodając ORDER BY nie zadziała: **

WITH RECURSIVE recursetree(id, parent_id, path, name) AS (
    SELECT 
     id, 
     parent_id, 
     array[id] AS path, 
     name 
    FROM tree WHERE parent_id = 0 
    UNION ALL 
    SELECT t.id, t.parent_id, rt.path || t.id, t.name 
    FROM tree t 
    JOIN recursetree rt ON rt.id = t.parent_id 
) 
SELECT * FROM recursetree ORDER BY path; 

Powyższy zachowa relacje rodzic dziecka (dzieci śledzić ich rodziców), ale stosowanie wszelkich innych ORDER BY (tj: imię - jak niektórzy zasugerował) spowoduje, że wynik straci jego relacje rodzic-dziecko.

+1

nie jest prosta orderby robi trick? –

+0

W ZAMÓWIENIU nie można umieszczać dzieci pod rodzicami, zamawiając je tylko po imieniu. – robdog

Odpowiedz

7

Zobacz także to (przetłumaczone) artykuł o CTE w PostgreSQL: wiki.phpfreakz.nl

Edycja: Spróbuj tego, za pomocą tablicy:

WITH RECURSIVE recursetree(id, parent_ids, firstname) AS (
    SELECT id, NULL::int[] || parent_id, name FROM tree WHERE parent_id = 0 
    UNION ALL 
    SELECT 
    t.id, 
    rt.parent_ids || t.parent_id, 
    name 
    FROM tree t 
    JOIN recursetree rt ON rt.id = t.parent_id 
) 
SELECT * FROM recursetree ORDER BY parent_ids; 
+0

Dzięki za link. Jednak sedno problemu pozostaje - muszę sortować według ścieżki, aby zachować porządek, ale muszę sortować elementy najwyższego poziomu według pola (w tym przypadku nazwa). – robdog

+0

Po prostu używaj tablicy w CTE, dziecko zawsze będzie miało więcej elementów w tablicy, ponieważ jest rodzicem, rozkaz ASCending poradzi sobie. –

+0

prawdopodobnie "ORDER BY parent_ids, firstname", aby zamówić elementy najwyższego poziomu również według nazwy (które będą miały wszystkie {0} jako ich dane_ rodzic) – araqnid