假设我的oracle DB中有以下表格:
ID: Name: Parent_ID:
123 a 234
345 b 123
234 c 234
456 d 345
567 e 567
678 f 567
我想要做的是为每个ID
找ULTIMATE parent ID
(描述为行,当你上升时,递归地,基于Parent_ID
你所在的行最后得到ID = Parent_ID
)。
所以,例如,345的父母是123而123的父母是234而234的父母是234(意味着它是链的顶端),因此345的最终父母是234 - 我希望这是有道理的......
所以,我的结果应如下所示:
ID: Name: Ult_Parent_ID: Ult_Parent_Name:
123 a 234 c
345 b 234 c
234 c 234 c
456 d 234 c
567 e 567 e
678 f 567 e
我今天刚刚发现了有关Oracle Connect By
声明的内容,所以这对我来说是全新的,但我想我的查询必须看起来像SOMETHING如下:
SELECT ID, Name, Parent_ID as Ult_Parent_ID,
(SELECT Name from MyTable t2 WHERE t2.ID = t1.Parent_ID) as Ult_Parent_Name
FROM MyTable t1
CONNECT BY PRIOR Parent_ID = ID;
现在,就像我说的,这是我对这种SQL的第一次尝试 - 这不工作(我收到以下错误[1]: ORA-01436: CONNECT BY loop in user data
并突出显示了表中的名称SQL编辑器),我也不知道在哪种/如何使用START WITH
子句进行此类查询,但它的逻辑对我来说似乎是正确的。
请帮助/帮助指出我正确的方向!!!
感谢!!!
答案 0 :(得分:4)
我认为你需要CONNECT_BY_ROOT:
select x.*, t2.name ultimate_name
from
(
select t.id, t.name, CONNECT_BY_ROOT parent_id ultimate_id
from toto t
start with t.id = t.parent_id
connect by nocycle prior id = parent_id
) x, toto t2
where x.ultimate_id = t2.id
;
这给出了:
456 d 234 c
345 b 234 c
123 a 234 c
234 c 234 c
678 f 567 e
567 e 567 e
答案 1 :(得分:1)
请尝试这个:
SELECT ID, Name, Parent_ID as Ult_Parent_ID,
(SELECT Name from MyTable t2 WHERE t2.ID = t1.Parent_ID) as Ult_Parent_Name,
LEVEL
FROM MyTable t1
CONNECT BY NOCYCLE Parent_ID = PRIOR ID
START WITH Parent_ID = ID;
我认为我们必须使用NOCYCLE
,因为你的根被定义了。
我添加了伪列LEVEL
仅用于说明目的。您不必须在最终查询中使用它。
SQL Fiddle包含您的测试数据
答案 2 :(得分:1)
CONNECT BY会给你直接的父母但是为了得到最终的父母,我会使用recursive subquery。 (Emmanuel所解释的CONNECT_BY_ROOT
也有效)
WITH r (id, parent, ultimate_parent, name, ultimate_parent_name, lvl) as
(SELECT id, parent_id AS parent, parent_id AS ultimate_parent, name, name as ultimate_parent_name, 0 lvl
FROM mytable
WHERE parent_id = id -- identifies a root
UNION ALL
SELECT m.id, r.id, ultimate_parent, m.name, r.ultimate_parent_name, r.lvl + 1
FROM r join mytable m on m.parent_id = r.id -- joins child with parent
WHERE m.parent_id <> m.id -- to avoid cycles
)
SELECT * FROM r ;
子查询的第一部分取根,第二部分连接子节点。 Parent
是直接父级,ultimate_parent
是最终父级。
答案 3 :(得分:0)
create table test_data(order_number number(10),line_id number(10),parent_line_id number(10));
insert into test_data values (1000, 101, 100);
insert into test_data values (1000, 100, '');
insert into test_data values (3000, 301, 300);
insert into test_data values (3000, 300, '');
select * from test_data
select * from test_data
where order_number in (1000,3000)
start with parent_line_id is null
connect by prior line_id= parent_line_id