SQL分层查询:查找给定任何父子ID的完整树(Oracle)

时间:2016-07-22 19:50:27

标签: sql oracle oracle11g

我正在努力进行分层SQL查询(使用Oracle)。假设我有一些带有唯一ID的小部件表。窗口小部件只能复制一次,我们会跟踪新窗口小部件中的父标识。例如,假设小部件100被复制并变为小部件101,然后是103,然后是105。

id    parent_id
100   
101   100
102
103   101
104
105   103

CREATE TABLE WIDGETS (ID NUMBER NOT NULL, PARENT_ID NUMBER);
INSERT INTO WIDGETS (ID, PARENT_ID) VALUES (100, null);
INSERT INTO WIDGETS (ID, PARENT_ID) VALUES (101, 100);
INSERT INTO WIDGETS (ID, PARENT_ID) VALUES (102, null);
INSERT INTO WIDGETS (ID, PARENT_ID) VALUES (103, 101);
INSERT INTO WIDGETS (ID, PARENT_ID) VALUES (104, null);
INSERT INTO WIDGETS (ID, PARENT_ID) VALUES (105, 103);

(102和104只是虚拟数据)

我正在尝试使用关系中的任何ID创建一个显示窗口小部件完整历史记录的查询。

因此,如果我为查询提供了“103”(或“100”......或“105”)的ID,我希望查询返回如下内容:

id    parent_id    
100   
101   100
103   101
105   103

我尝试过使用CONNECT BY PRIOR,但我需要以ID开头才能使用start。例如,我可以显示完整的树,为查询提供原始ID:

select parent_id as from_id, id as to_id
from WIDGETS
start with id = 100
CONNECT BY PRIOR id = parent_id;

from_id   to_id
null      100
100       101
101       103
103       105

但如果我不一定知道id的开头怎么办?是否可以找到原始ID,然后从那里获取完整的树?

2 个答案:

答案 0 :(得分:1)

通过向后遍历树来计算开始,直到你碰到一片叶子。 SELECT parent_id AS from_id, ID AS to_id FROM WIDGETS START WITH ID = ( SELECT ID FROM WIDGETS WHERE CONNECT_BY_ISLEAF=1 START WITH ID = 105 CONNECT BY ID = PRIOR parent_id ) CONNECT BY PRIOR ID = parent_id;

答案 1 :(得分:-1)

下面的@Input是您传递给存储过程的输入ID。试试这个,希望它有所帮助:

DECLARE @Parent int;

WHILE (Select @Parent = PARENT_ID From Widgets Where ID = @Input) Is NOT NULL
BEGIN
Set @Input = @Parent
END
Set @Parent = @Input

declare @Hierarchy table(Member int)
INSERT INTO @Hierarchy(Member) Values (@Parent)
WHILE (Select @Input = ID From Widgets Where PARENT_ID = @Parent) Is NOT NULL
BEGIN
SET @Parent = @Input
INSERT INTO @Hierarchy(Member) Values (@Parent)
END

Select * From @Hierarchy