CTE递归以获得每个父级

时间:2016-04-15 22:16:31

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

我有以下查询返回父项和(仅前2个)后代以及子计数。但是,查询只返回2个以上的后代(这是SQL小提琴:http://sqlfiddle.com/#!6/6489b/5)。

;WITH cte AS (
SELECT  [EntryId],
        [Title],
        [ParentId],         
        [Depth],
        ROW_NUMBER() OVER (ORDER BY Date DESC) [Rn],
        CAST(EntryId AS VARCHAR(MAX)) [Path],
        1 AS DescendentCount 
FROM    ViewEntryRecords
WHERE   [Depth] = 0 AND DiscussionWallId = @DiscussionWallId
UNION ALL
SELECT  e.[EntryId],
        e.[Title],
        e.[ParentId],
        e.[Depth],
        Rn,
        [Path] + ',' + CAST(e.EntryId AS VARCHAR(MAX)),
        P.DescendentCount + 1
FROM    ViewEntryRecords S
        JOIN cte P ON P.EntryId = S.ParentId 
        WHERE S.Depth=0 AND P.DescendentCount <= 2
)

SELECT  [EntryId],
    [Title],
    [ParentId],
    [Depth],
    ChildCount,
    DescendentCount
FROM cte c1
    OUTER APPLY (SELECT COUNT (*) - 1 AS ChildCount 
                 FROM cte c2 
                 WHERE c2.[Path] LIKE c1.[Path] + '%'
                ) oa
WHERE   Rn BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1
ORDER BY c1.[ParentId],  Date DESC

这是输出。我将DescendentCount包括在内进行测试:

 EntryId    Title   ParentId    Depth   ChildCount  DescendentCount
 15         a       NULL        0       5           1
 4          d       NULL        0       1           1
 1          c       NULL        0       7           1
 1          s       NULL        0       7           1
 22         a1      4           1       0           2
 24         da      15          1       0           2
 23         32      15          1       0           2
 16         b       15          1       2           2
 21         n       16          1       0           3
 20         y       16          1       0           3

因此,应该列出ID为16的条目,因为我使用P.DescendentCount&lt; = 2 where condition。但是,我看到DescendentCount没有像我想象的那样增加。有没有办法限制后代项目?

1 个答案:

答案 0 :(得分:1)

你必须再次获得DescendentCount并在WHERE原因中将其<=2(因为你只想要前两个后代)。 我修改了您在SQL Fiddle中提供的查询并在我的SqlServer Management Studio中运行它。以下TSQL是完美的工作:

;WITH cte AS (
SELECT  [EntryId],
        [Title],
        [ParentId],         
        [Depth],
        ROW_NUMBER() OVER (ORDER BY EntryId DESC) [Rn],
        CAST(EntryId AS VARCHAR(MAX)) [Path],
        1 AS DescendentCount 
FROM    Entries
WHERE   [Depth] = 0 
UNION ALL
SELECT  e.[EntryId],
        e.[Title],
        e.[ParentId],
        e.[Depth],
        Rn,
        [Path] + ',' + CAST(e.EntryId AS VARCHAR(MAX)),
        c.DescendentCount + 1
FROM    Entries e
        JOIN cte c ON c.EntryId = e.ParentId 
        WHERE e.Depth=1 AND c.DescendentCount <= 2
)

SELECT Raihan.[EntryId]
    ,Raihan.[Title]
    ,Raihan.[ParentId]
    ,Raihan.[Depth]
    ,Raihan.ChildCount
    ,Raihan.DescendentCount
    --,Raihan.NewRN
    FROM
(
SELECT  [EntryId],
    [Title],
    [ParentId],
    [Depth],
    ChildCount,
    DescendentCount,
    ROW_NUMBER() OVER (PARTITION BY DescendentCount ORDER BY DescendentCount DESC) AS NewRN
FROM  cte c1
    OUTER APPLY (SELECT COUNT (*) - 1 AS ChildCount 
                 FROM cte c2 
                 WHERE c2.[Path] LIKE c1.[Path] + '%'
                ) oa
) AS Raihan
WHERE Raihan.NewRN<=2 
ORDER BY Raihan.[ParentId]