2017-05-26 25 views
1

我有建立树递归查询,同Postgresql。如何在递归查询中保存所有孩子的第一个ID?

CREATE TABLE geo (
    id int not null primary key, 
    parent_id int references geo(id), 
    name varchar(1000) 
); 

INSERT INTO geo 
(id, parent_id, name) 
VALUES 
(1, null, 'Планета Земля'), 
(2, 1, 'Континент Евразия'), 
(3, 1, 'Континент Северная Америка'), 
(4, 2, 'Европа'), 
(5, 4, 'Россия'), 
(6, 4, 'Германия'), 
(7, 5, 'Москва'), 
(8, 5, 'Санкт-Петербург'), 
(9, 6, 'Берлин'); 

WITH RECURSIVE r AS (
    SELECT id, parent_id, name, 1 AS level 
    FROM geo 
    WHERE id = 4 

    UNION ALL 

    SELECT geo.id, geo.parent_id, geo.name, r.level + 1 AS level 
    FROM geo 
     JOIN r 
      ON geo.parent_id = r.id 
) 

SELECT * FROM r; 

如何选择根ID为组中的每个孩子? 现在的结果是:

id | parent_id |  name  | level 
----+-----------+-----------------+------- 
    4 |   2 | Европа   |  1 
    5 |   4 | Россия   |  2 
    6 |   4 | Германия  |  2 
    7 |   5 | Москва   |  3 
    8 |   5 | Санкт-Петербург |  3 
    9 |   6 | Берлин   |  3 

但我需要,财产以后说:

id | parent_id |  name  | level| root_id 
----+-----------+-----------------+------+--------- 
    4 |   2 | Европа   |  1| null 
    5 |   4 | Россия   |  2| 4 
    6 |   4 | Германия  |  2| 4 
    7 |   5 | Москва   |  3| 4 
    8 |   5 | Санкт-Петербург |  3| 4 
    9 |   6 | Берлин   |  3| 4 

回答

3

您可以从非递归部分,类似于您与level做了什么携带过来:

WITH RECURSIVE r AS (
    SELECT id, parent_id, name, 1 AS level, id as root 
    FROM geo 
    WHERE id = 4 

    UNION ALL 

    SELECT geo.id, geo.parent_id, geo.name, r.level + 1 AS level, r.root 
    FROM geo 
    JOIN r ON geo.parent_id = r.id 
) 
SELECT id, parent_id, name, level, 
     nullif(root, id) as root 
FROM r; 

nullif()是必要的,因为你想要显示nullid = root

在线案例:http://rextester.com/BPP29069

相关问题