为了避免在带有2个Oracle / SQL表的递归CTE中进行循环引用

时间:2018-07-09 11:49:28

标签: sql oracle

“部门”和“子部门”这两个表具有相同的ID。我试图递归地获取直接和间接向AB报告的所有ID。 BC向AB报告,因此4,5,6间接向AB报告,直到获取最后一个ID。

从Id 9到BC都有一个循环引用。我想避免循环引用。 我正在Oracle 11g和SQL Server 2012中尝试 部门

Name     id
AB          1
AB          2
AB          3
BC          4
BC          5
BC          6
CD          7
CD          8
EF          9
EF         10
EF         11

子部门

ID      Reporting
1
2
3         BC
4
5         CD
6
7
8         EF
9         BC
10
11

查询:

With reportinghierarchy (Name, Id, Reporting, lvl) As
    (   
    --Anchor
    Select A.name,
           A.id,
           reporting,
           0 
    from department A, 
         subdepartment B
    where A.id=B.id 
    and A.name='AB'        
    Union All        
    --Recursive member
    Select C.name,
           C.id,
           D.reporting, 
           lvl+1 
    from department C, 
         subdepartment D, 
         reportinghierarchy R
    Where C.name != 'AB' 
    and C.Id =D.id 
    and C.Name = R.reporting
    And R.Reporting is not null
    )
Select * from reportinghierarchy;

获取错误消息“ ORA-32044:执行递归WITH时检测到周期”

1 个答案:

答案 0 :(得分:1)

我认为您只是在寻找cycle子句:

with reportinghierarchy (name, id, reporting, lvl) as
(
  select a.name, a.id, reporting, 0
  from department a
  join subdepartment b
  on b.id = a.id
  where a.name='AB'
  union all
  select c.name, c.id, d.reporting, lvl+1
  from reportinghierarchy r
  join department c
  on c.name = r.reporting
  join subdepartment d
  on d.id = c.id
  where c.name != 'AB'
  and r.reporting is not null
)
cycle reporting set is_cycle to 1 default 0
select *
from reportinghierarchy;

与您的样品日期一起得出的结果:

NAME         ID REPORTING        LVL I
---- ---------- --------- ---------- -
AB            1                    0 0
AB            2                    0 0
AB            3 BC                 0 0
BC            6                    1 0
BC            5 CD                 1 0
BC            4                    1 0
CD            8 EF                 2 0
CD            7                    2 0
EF           11                    3 0
EF           10                    3 0
EF            9 BC                 3 1

11 rows selected. 

您可以过滤is_cycle伪列,和/或通过列出您想查看的列而不是使用*来将其从结果集中排除。< / p>

详细了解递归子查询分解的工作原理in the documentation