创建没有rootrecord的递归CTE

时间:2014-10-24 09:52:46

标签: sql-server tsql recursion

对于令人震惊的标题我抱歉,我试图描述但不确定我是否达到了目的。希望以下将解释它

我从一个包含以下信息的表开始

Party Id    Party Name    Party Code   Parent Id
1           Acme 1        ACME1        1
2           Acme 2        ACME2        1
3           Acme 3        ACME3        3
4           Acme 4        ACME4        4
5           Acme 5        ACME5        4
6           Acme 6        ACME6        6

正如您所看到的,这对于递归CTE来说并不完美,因为在父记录不存在的情况下,它不是自身的父级(参见第1,3和6行)。然而,有些人通常是父母。

因此我尝试在CTE中修改此表,然后将该CTE的输出作为递归查询的一部分...这似乎没有运行得很好(还没有错误)所以我想知道我是否设法创建了一个无限循环或其他一些错误,只是将查询减慢到爬行而不是杀死它

我的代码如下......请分开!

--This is my attempt to 'clean' the data and set records parented to themselves as the 'anchor' 
--record
WITH Parties
AS
(Select CASE
    WHEN Cur_Parent_Id = Party_Id THEN NULL
    ELSE Cur_Parent_Id
END AS Act_Parent_Id
, Party_Id
, CUR_PARTY_CODE
, CUR_PARTY_NAME
FROM EDW..TBDIMD_PARTIES
WHERE CUR_FLG = 1),

--In this CTE I referred to my 'clean' records from above and then traverse through them
--looking at the actual parent record identified
linkedParties
AS
(
Select Act_Parent_Id, Party_Id, CUR_PARTY_CODE, CUR_PARTY_NAME, 0 AS LEVEL
FROM Parties
WHERE Act_Parent_Id IS NULL

UNION ALL

Select p.Act_Parent_Id, p.Party_Id, p.CUR_PARTY_CODE, p.CUR_PARTY_NAME, Level + 1
FROM Parties p
inner join
linkedParties t on p.Act_Parent_Id = t.Party_Id
)

Select *
FROM linkedParties
Order By Level

根据我之前提供的数据,我期望的结果是;

Party Id    Party Name    Party Code   Parent Id    Level
1           Acme 1        ACME1        1            0
3           Acme 3        ACME3        3            0
4           Acme 4        ACME4        4            0
6           Acme 6        ACME6        6            0
2           Acme 2        ACME2        1            1
5           Acme 5        ACME5        4            1

如果一切似乎都没问题,那么我会假设它只是一个处理问题,并开始调查,但我对CTE不太满意,所以希望确保错误不是我的,然后再寻找其他地方

非常感谢

1 个答案:

答案 0 :(得分:1)

我认为你让它变得比它需要的更复杂:)。

drop table #temp
GO
select 
    *
into #temp
from (
    select '1','Acme 1','ACME1','1' union all
    select '2','Acme 2','ACME2','1' union all
    select '3','Acme 3','ACME3','3' union all
    select '4','Acme 4','ACME4','4' union all
    select '5','Acme 5','ACME5','4' union all
    select '6','Acme 6','ACME6','6'
) x ([Party Id],[Party Name],[Party Code],[Parent Id])
GO

;with cte as (
    select
        *, 
        [Level] = 0
    from #temp
    where 1=1
        and [Party Id]=[Parent Id] --assuming these are root records

    union all 

    select
        t.*,
        [Level] = c.[Level]+1
    from #temp t
    join cte c
        on t.[Parent Id]=c.[Party Id]
    where 1=1
        and t.[Party Id]<>t.[Parent Id]  --prevent matching root records with themselves creating infinite recursion
)
select
    *
from cte

*应该用实际的列名替换)