Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
596 views
in Technique[技术] by (71.8m points)

sql - PostgreSQL recursive with

I need help with a recursive query. Assuming the following table:

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

I can retrieve a list of all people and their children with the following query:

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;

How can I list them in order, and also sort the first level items by name? For example, the desired output would be:

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

Thanks,

**EDIT. Please note that adding an ORDER BY won't work: **

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;

The above will retain the parent child relationship (children follow their parents), but applying any other ORDER BY clause (ie: name - like some have suggested) will cause the result to lose it's parent-child relationships.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

See also this (translated) article about CTE's in PostgreSQL: wiki.phpfreakz.nl

Edit: Try this one, using an array:

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;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...