WITH RECURSIVE 只返回非递归项

WITH RECURSIVE only returning the non-recursive term

我有一个 table object 由以下字段组成:

table 内容的构建使得每个对象都有一个父对象,除了具有 idobject_parentnull 的树的顶部节点。有很多棵树,每棵树都有不同的顶部节点。

给定一个叶节点,我想获取该树的顶部节点的字段。所以我有以下查询:

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。

问题是这个查询只是 returns 叶节点本身,也就是说,它似乎只执行非递归情况。

通过手动执行递归查询并将结果用作以下查询的 "input",我可以看到我正在正确地提升树:

 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)

提前致谢。

不是向下延伸森林(从所有的根开始),而是向上走,走向根。 (这也更有效,因为您不必在选择所需路径之前生成所有路径)

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