我有一个表object
,包含以下字段:
id
:记录ID idobject_parent
:对象的父级label
:描述对象的任意字符串构造表内容,以便每个对象都有一个父对象,除了idobject_parent
值为null
的树的顶部节点。有许多树,每个树都有不同的顶部节点。
给定一个叶子节点,我想得到该树的顶部节点的字段。所以我有以下查询:
with recursive parent_object(id) as (
select id,idobject_parent, label from object o
union
select oe.id, oe.idobject_parent, oe.label from object oe join parent_object pc on (oe.id = pc.idobject_parent) where oe.idobject_parent is not null
)
select id,idobject_parent,label from parent_object where id = 340;
340
是我用于此测试的任意叶ID。
问题是这个查询只返回叶子节点本身,即它似乎只是执行非递归的情况。
通过手动执行递归查询并将结果用作下一个的“输入”,我可以看到我正在提升树:
db=# select oe.id,oe.idobject_parent,oe.label from object oe join (select 340 as id,480 as idobject_parent, 'hello' as label) as pc on (oe.id = pc.idobject_parent) where oe.idobject_parent is not null;
id | idobject_parent | label
-----+-----------------+-----------
480 | 105 | xxxxxxx
(1 row)
db=# select oe.id,oe.idobject_parent,oe.label from object oe join (select 480 as id,105 as idobject_parent, 'hello' as label) as pc on (oe.id = pc.idobject_parent) where oe.idobject_parent is not null;
id | idobject_parent | label
-----+-----------------+-----------------------
105 | 102 | yyyyyyy
(1 row)
db=# select oe.id,oe.idobject_parent,oe.label from object oe join (select 105 as id,102 as idobject_parent, 'hello' as label) as pc on (oe.id = pc.idobject_parent) where oe.idobject_parent is not null;
id | idobject_parent | label
----+-----------------+-------
(0 rows)
我的查询有什么问题?为什么我没有得到这个?
id | idobject_parent | label
-----+-----------------+-----------------------
105 | 102 | yyyyyyy
(1 row)
提前谢谢。
答案 0 :(得分:1)
不是向下延伸森林(从所有根开始),而是向上走,朝向根。 (这也更有效,因为在选择你想要的路径之前你不必生成所有路径)
-- sample structure
CREATE TABLE thetree
( id INTEGER not null primary key
, parent INTEGER references thetree(id)
-- , label text
);
-- make some data
INSERT INTO thetree(id,parent)
SELECT gs, gs / 3 FROM generate_series(0,20) gs;
UPDATE thetree SET parent = NULL where parent=0;
CREATE UNIQUE INDEX ON thetree(parent,id);
-- SELECT * FROM thetree;
WITH RECURSIVE zzz AS (
SELECT COALESCE(parent,id) AS root
, parent AS par
, id AS me
, 0::integer AS upsteps
FROM thetree WHERE id = 17
UNION ALL
SELECT COALESCE(t.parent,zzz.root) AS root
, t.parent AS par
, zzz.me AS me
, 1+ zzz.upsteps AS upsteps
FROM thetree t
JOIN zzz ON zzz.par = t.id
)
SELECT *
-- SELECT root,me
FROM zzz
WHERE zzz.par IS NULL -- eliminate partial paths
;
仅供参考向下树木行走:
-- treewalk; starting with roots: downward
WITH RECURSIVE omg AS (
SELECT id AS root
, id AS me
, 0::integer AS upsteps
FROM thetree WHERE parent IS NULL -- this is the root of a tree
UNION ALL
SELECT omg.root AS root
, t.id AS me
, 1+ omg.upsteps AS upsteps
FROM thetree t
JOIN omg ON t.parent = omg.me
)
SELECT *
FROM omg
WHERE omg.me = 17
;