Oracle Connect By Prior 递归查询语法

问题描述 投票:0回答:4

假设我的 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
语句,所以这对我来说是全新的,但我想象我的查询必须看起来如下:

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
子句进行此类查询,但它的逻辑对我来说似乎是正确的。

请帮助/帮助指出我正确的方向!!!

谢谢!!!

sql oracle recursive-query
4个回答
6
投票

我认为 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
投票

请尝试这个:

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 与您的测试数据


1
投票

CONNECT BY 将为您提供直接父级,但为了获得最终父级,我将使用递归子查询。 (

CONNECT_BY_ROOT
正如 Emmanuel 所解释的那样也有效)

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
是最终父级。


0
投票

创建表test_data(order_number号(10),line_id号(10),parent_line_id号(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
© www.soinside.com 2019 - 2024. All rights reserved.