Sql Server CTE父子递归

时间:2014-04-07 10:24:40

标签: sql sql-server recursion common-table-expression

我有以下表结构:

create table Test(
  ParentId int,
  ChildId int
 )

insert into Test(ParentId, ChildId)
select 1, NULL
union
select 1, 2
union
select 1, 3
union
select 2, NULL
union
select 2, 5
union
select 5, 6
union 
select 6, 5
union 
select 6, 8

我试图构建所有父子DIRECT和INDIRECT关系的结果集。所以假设我传递了ParentID = 2的参数,我希望结果集返回如下:

ParentId    ChildId
-------------------
2           NULL
2           5
5           6
6           8
1           2

所以基本上这个显示所有可能的链接,可以在一个表中找到Parent ID = 2。 从Parent本身开始,它具有Child Id,然后与Child Id 6具有其他关系。此外,父ID 2也属于父ID 1,其也应显示在结果集中。请注意,关系可以扩展到 N个级别。我希望你明白我在这里想要达到的目标,如果没有,请告诉我,以便我能更清楚地解释。

到目前为止,我已经提出了下面的递归查询,但它会抛出一个错误,如下所示:

DECLARE @ID INT = 2

;WITH MyCTE
AS (
    SELECT ParentId
        ,ChildId
    FROM Test
    WHERE ParentId = @ID

    UNION ALL

    SELECT T.ParentId
        ,Test.ChildId
    FROM Test
    INNER JOIN MyCTE T ON Test.ParentID = T.ChildId
    WHERE Test.ParentID IS NOT NULL
    )
SELECT *
FROM MyCTE

Error:
The statement terminated. The maximum recursion 100 has been exhausted before statement completion

我已经在SQLFiddle here上提供了代码供您测试并尝试。

我真的很感激任何指导并帮助我实现理想结果的人。

1 个答案:

答案 0 :(得分:4)

正如#Mikael Eriksson所说:"您的数据中有循环引用。 5是6的父级,6是5的父级。"

同样在递归部分中,您从上一步输出ParentId,而不是仅从找到的行输出。{/ p>

declare @Test table (ParentId int, ChildId int)

insert into @Test (ParentId, ChildId)
select 1, null
union all
select 1, 2
union all
select 1, 3
union all
select 2, null
union all
select 2, 5
union all
select 5, 6
union all
--select 6, 5
--union all
select 6, 8

declare @id int = 2

;with MyCTE as (
    select ParentId, ChildId
    from @test
    where ParentId = @id

    union all

    select t2.ParentId, t2.ChildId
    from MyCTE t1
    inner join @Test t2 on t1.ChildId = t2.ParentId
)

select * from MyCTE

我不明白的另一件事是你为什么会有ChildId为空且ParentId不为空的行。怎么可能呢?

这是否意味着您拥有其父项已知的未知项目?