WITH RECURSIVE 只返回非递归项
WITH RECURSIVE only returning the non-recursive term
我有一个 table object
由以下字段组成:
id
: 记录id
idobject_parent
: 对象的父对象
label
: 描述对象的任意字符串
table 内容的构建使得每个对象都有一个父对象,除了具有 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。
问题是这个查询只是 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
;
我有一个 table object
由以下字段组成:
id
: 记录ididobject_parent
: 对象的父对象label
: 描述对象的任意字符串
table 内容的构建使得每个对象都有一个父对象,除了具有 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。
问题是这个查询只是 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
;