我有自引用表 - HIERARCHY(id, name, parent_id)
。
所以我需要通过该层次结构的任何节点获取所有层次结构。例如我们有树,其中 h1
, h2
是根:
-(h1)
| |_(h1_1)
| | |_(h1_1_2)
| |_(h1_2)
| |_(h1_2_1)
-(h2)
| |_(h2_1)
| |_(h2_2)
|
我需要的是通过这棵树的任何节点获取所有树,例如根 h1
通过 h1_2
-(h1)
|_(h1_1)
get | |_(h1_1_2) by h1_2 or h1_2_1, etc
|_(h1_2)
|_(h1_2_1)
我写了查询:
WITH RECURSIVE hierarchy_with_parents(id) AS (
SELECT l.id, l.name, l.parent_id FROM hierarchy AS l WHERE l.id = <any_row_id>
UNION ALL
SELECT lc.id, lc.name, lc.parent_id FROM hierarchy lc, hierarchy_with_parents lwp WHERE lc.id = lwp.parent_id
), hierarchy_with_children(id) AS (
SELECT l.id, l.name, l.parent_id FROM hierarchy AS l WHERE l.id
IN ( -- sub-query for getting parent id
SELECT
lwp.id
FROM hierarchy_with_parents AS lwp
WHERE lwp.parent_id IS NULL
)
UNION ALL
SELECT lc.id, lc.name, lc.parent_id FROM hierarchy lc, hierarchy_with_children lwc WHERE lc.parent_id = lwc.id
)
SELECT * FROM hierarchy_with_children
hierarchy_with_parents
- 将子树从子树返回到父树(包括),
hierarchy_with_children
- 返回所有树。
似乎一切正常,但我不是 DB 专家,我想知道关于我的查询的限制和评论。也欢迎任何其他适用于 PostgreSQL 和 Oracle 11g 的解决方案。
谢谢。
最佳答案
给定 :input_node
,首先找到包含该节点的子树的根。这是在 find_root
分解子查询中完成的。然后简单地收集所有链接到该根的行。我需要在外部查询中调用 NVL()
以防 :input_node
已经是根;在这种情况下,find_root
不返回任何行。当用作标量子查询时,它被视为 null
(至少在 Oracle 中是这样),因此我可以使用 NVL()
来修复它。
with
hierarchy as (
select 2 as child, 1 as parent from dual union all
select 3, 2 from dual union all
select 4, 1 from dual union all
select 5, 4 from dual union all
select 7, 6 from dual union all
select 8, 7 from dual union all
select 9, 6 from dual
),
find_root as (
select parent as rt
from hierarchy
where connect_by_isleaf = 1
start with child = :input_node
connect by child = prior parent
)
select child, parent
from hierarchy
start with parent = nvl((select rt from find_root), :input_node)
connect by parent = prior child;
关于sql - 如何通过任意节点获取树(SQL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39956475/