2010-07-22 35 views
12
ile yinelenen

Yinelemeli bir sorguda yardıma ihtiyacım var. Ben tüm insanların listesi ve aşağıdaki sorgu ile çocuklarını alabilirsinizPostgreSQL

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

: Aşağıdaki tablo varsayarsak da

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; 

ben sırayla listeleyebilirsiniz Nasıl ve ilk seviye öğeleri sıralamak isimle? Örneğin, arzu edilen çıkış olacaktır:

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

sayesinde

** DÜZENLEME. Bir ORDER BY ekleyerek işe yaramaz lütfen unutmayın: **

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; 

yukarıda ana çocuk ilişkisini (çocuklar ebeveynlerini izleyin) devam ettirir fakat BY yan tümcesinde başka SİPARİŞ uygulayarak olacaktır (yani: adı - gibi bazı önerdi) sonucun ebeveyn-çocuk ilişkilerini kaybetmesine neden olacak.

+1

hile yapıyor basit orderBy değil midir: bir dizi kullanarak, bu bir deneyin? –

+0

Bir SİPARİŞ FORMU, çocukları ebeveynlerinin altına yerleştirmeyecek, yalnızca her şeyi ismine göre sıralayacaktır. – robdog

cevap

7

da PostgreSQL CTE'ler ilgili bu (çevrilmiş) makalesine bakın: wiki.phpfreakz.nl

Düzenleme:

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

Bağlantı için teşekkürler. Bununla birlikte, problemin özü hala devam ediyor - Siparişi korumak için yola göre sıralama yapmam gerekiyor, ancak üst düzey öğeleri bir alanla (bu durumda adında) sıralamalıyım. – robdog

+0

Sadece CTE'de bir dizi kullanın, bir çocuk her zaman dizide ebeveynlerin olduğu gibi daha fazla öğeye sahip olacak, bir ASCending siparişi hile yapacaktır. –

+0

Muhtemelen "ORDER BY parent_ids, firstname" ile en üst düzeydeki öğeleri adlarına göre sıralamak için (bunların hepsi {0} kendi parent_idleri gibi) – araqnid