【问题标题】:Sql Server CTE Parent Child recursiveSql Server CTE 父子递归
【发布时间】:2014-05-19 12:50:37
【问题描述】:

我有以下表结构:

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

我正在尝试构建所有父子直接和间接关系的结果集。所以假设我传递了 ParentID = 2 的参数,我希望结果集完全返回如下:

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

所以基本上这显示了所有可能的链接,可以在一个表中找到父 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 上供大家测试和尝试。

我非常感谢任何指导和帮助我实现预期结果的人。

【问题讨论】:

  • 您的数据中有循环引用。 5 是 6 的父级,6 是 5 的父级。这使得递归不断循环......这就是你的数据的实际样子吗?
  • 除了那个循环引用之外 - 在结果的末尾获得 (Parent, Child) 1, 2 的条件是什么?
  • @MikaelEriksson 是的,这就是数据的样子,因为两个人之间可能存在多种类型的关系。
  • @AllanS.Hansen 我还没有设置条件。我正在寻找可以返回这样一个结果集的通用东西。
  • 您在这里找到答案了吗?如果@GriGrim 不适合您,您可以发布自己的解决方案吗?我也有类似的问题。

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


【解决方案1】:

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

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

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 不为空。怎么可能?

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

【讨论】:

  • ChildId 为 null 以指定特定行是父行。更像是根节点。
  • 如果是根节点则parentid为null,childid填写。根不能有父级,但会有子级。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-23
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
相关资源
最近更新 更多