CTE查找相同的根父级而不进行无限循环

时间:2014-01-10 17:11:58

标签: sql tsql recursion common-table-expression

我有一个CTE递归查询,正在寻找每个孩子的根父母。在正常情况下,根父级的ParentID应为null。但是,如果“root parent”(请参阅​​下面的childID 4)具有应该位于同一层次结构下的ParentID,则会创建一个无限循环。

正常情况

ChildID   ParentID  StartDate  Root Parent
1         2         2014       4
2         3         2013       4
3         4         2012       4
4         NULL      2011       4
5         6         2012       6
6         NULL      2013       6

无限循环

ChildID   ParentID  StartDate  Root Parent  Desired Root Parent
1         2         2014       4            1
2         3         2013       1            1
3         4         2012       2            1
4         1         2011       3            1
5         6         2012       6            6
6         6         2013       6            6

我创建了以下查询来停止无限循环,但是ChildID为1,2,3和4的根父母都是不同的。我的目标是根据StartDate(分配最新的)将Root parent 1分配给ChildID 1,2,3和4。

我不知道从哪里开始。任何帮助将不胜感激。感谢。

With a as
(   select 1 as childID, 2 as ParentID, 2014 as startDate
    union all select 2 as childID, 3 as ParentID , 2013 as startDate
    union all select 3 as childID, 4 as ParentID, 2012 as StartDate
    --union all select 4 as childID, NULL as ParentID, 2011 as StartDate
    union all select 4 as childID, 1 as ParentID, 2011 as StartDate
    union all select 5 as childID, 6 as ParentID, 2012 as StartDate
    union all select 6 as childID, NULL as ParentID, 2013 as StartDate
)
, RCTE AS
(   SELECT childID
    , ParentID
    , 1 AS Lvl
    , '/' + convert(varchar(max), rtrim(childID)) + '/' [path]
    , startDate
    from a

    UNION ALL

    SELECT rc.childID
    , rh.ParentID
    , Lvl+1 AS Lvl
    , rc.[path] + convert(varchar(max),rtrim(rh.childID)) + '/'
    , rc.startDate
    FROM a rh 
        INNER JOIN RCTE rc ON
    rh.childID = rc.ParentID and 
    rh.childID<>rh.ParentID
    WHERE rc.[path] not like '%/' + convert(varchar(max),rtrim(rh.ParentID)) + '/%'
)
, CTE_RN AS
(    SELECT * 
         , ROW_NUMBER() OVER (PARTITION BY r.childID ORDER BY r.Lvl DESC) RN
     FROM RCTE r
)

SELECT r.childID, 
    case 
        when r.ParentID is null then childID 
        else ParentID 
    end as ParentID
    , rn,[path]
    , r.startDate
FROM CTE_RN r
WHERE RN=1
Order by ChildID, RN

0 个答案:

没有答案