Oracle通过连接来查找子,祖先对

时间:2016-01-07 23:56:55

标签: sql oracle connect-by

我正在尝试编写一个查询来获取所有节点及其祖先。数据库存储树(节点及其子/父)。我知道connect by可以给所有祖先,当与start with子句结合使用时,你可以获得单个节点的所有祖先。

这是一个快速举例说明我的目的。

节点边缘表:

+---------+-----------+
|child_id |parent_id  |
+---------+-----------+
|2        |1          |
|3        |2          |
|4        |2          |
|5        |4          |
+---------+-----------+

我写的查询是:

select parent_id, child_id
from edges
start with child_id = 5
connect by child_id = prior parent_id

给出:

+---------+-----------+
|child_id |parent_id  |
+---------+-----------+
|2        |1          |
|4        |2          |
|5        |4          |
+---------+-----------+

我正在寻找的是这样的:

+---------+-----------+
|child_id |parent_id  |
+---------+-----------+
|2        |1          |
|3        |2          |
|3        |1          |
|4        |2          |
|4        |1          |
|5        |4          |
|5        |2          |
|5        |1          |
+---------+-----------+

因此每个节点都有一个记录,每个节点的祖先一直到根。我在构建查询以获得此结果时遇到了一些麻烦。有什么建议吗?

谢谢, mcangus

3 个答案:

答案 0 :(得分:1)

使用CONNECT_BY_ROOT运算符:

WITH edges (child_id, parent_id) AS (
    SELECT 2, 1 FROM DUAL UNION ALL
    SELECT 3, 2 FROM DUAL UNION ALL
    SELECT 4, 2 FROM DUAL UNION ALL
    SELECT 5, 4 FROM DUAL
)
SELECT
    child_id, CONNECT_BY_ROOT parent_id parent_id
FROM
    edges
CONNECT BY
    PRIOR child_id = parent_id
ORDER BY
    child_id, parent_id DESC;

答案 1 :(得分:0)

以下查询解决了您的问题:

with tree (childid, parentid)
as 
(select child_id, parent_id from 
 edges 
union all
select t.childid, g.parent_id
from tree  t
join edges g
on t.parentid = g.child_id)
select * from tree 
order by childid, parentid desc

答案 2 :(得分:0)

我不认为“开始”会做你打算做的事情。这将限制您的根行,这就是您获得有限结果集的原因。您还希望CONNECT_BY_ROOT不仅可以获取child_id,还可以获取根行的child_id。免责声明:我不是一个神谕大师,我只是有一段时间。

SYS_CONNECT_BY_PATH只是额外信息。

select CONNECT_BY_ROOT child_id "CHILD_ID", parent_id, SYS_CONNECT_BY_PATH(child_id, '/') "PATH"
from edges
connect by child_id  = prior parent_id;

结果:

CHILD_ID    PARENT_ID   PATH
2   1   /2
3   2   /3
3   1   /3/2
4   2   /4
4   1   /4/2
5   4   /5
5   2   /5/4
5   1   /5/4/2

查看docs

相关问题