递归查询SQL Server无法按预期工作

时间:2016-07-08 09:24:40

标签: sql-server recursion recursive-query

提前感谢您的帮助。我仍然是MS SQL数据库的新手,但我想知道为什么我对MSSQL的递归查询不会返回我期望的值。我完成了我的研究,最底层是我提出的代码。可以说我有下表...

CategoryID    ParentID    SomeName
1             0           hmm
2             0           err
3             0           woo
4             3           ppp
5             4           ttt

我期待下面的查询返回3 4 5.我基本上想要根据我在递归查询中传递的类别ID获取其自包含的类别id的层次列表。谢谢你的帮助。

GO
WITH RecursiveQuery (CategoryID)
AS
(
-- Anchor member definition
    SELECT a.CategoryID 
    FROM [SomeDB].[dbo].[SomeTable] AS a
    WHERE a.ParentID = CategoryID 
    UNION ALL
-- Recursive member definition
    SELECT b.CategoryID
    FROM [SomeDB].[dbo].[SomeTable] AS b
    INNER JOIN RecursiveQuery AS d
        ON d.CategoryID = b.ParentID
)
-- Statement that executes the CTE
SELECT o.CategoryID
FROM [SomeDB].[dbo].[SomeTable] AS o
INNER JOIN RecursiveQuery AS d
    ON d.CategoryID = 3
GO

2 个答案:

答案 0 :(得分:2)

如果您想要来自特定根目录的树:

DECLARE @rootCatID int = 3

;WITH LessonsTree (CatID)
AS
(
    SELECT a.CategoryID
    FROM [EducationDatabase].[dbo].[LessonCategory] AS a
    WHERE a.CategoryID = @rootCatID ---<<<

    UNION ALL

    SELECT b.CategoryID
    FROM LessonsTree as t
    INNER JOIN [EducationDatabase].[dbo].[LessonCategory] AS b
        ON b.ParentID = t.CatID
)
SELECT o.*
FROM LessonsTree t
INNER JOIN [EducationDatabase].[dbo].[LessonCategory] AS o
    ON o.CategoryID = t.CatID

答案 1 :(得分:0)

如评论中所述,锚不受限制。最简单的解决方案是在锚点中添加标准

with RecursiveQuery (theID)
AS
(
    SELECT a.ParentID --root id=parentid to include it and to prevent an extra trip to LessonCategory afterwards
    FROM  [LessonCategory] AS a
    WHERE a.ParentID = 3 --restriction here
    UNION ALL
    SELECT b.CategoryID
    FROM [LessonCategory] AS b
    INNER JOIN RecursiveQuery AS d
        ON d.theID = b.ParentID
)
SELECT* from RecursiveQuery

另一个选择是让递归查询是通用的(没有受限制的锚)并让它保持rootid。然后对cte的查询可以限制rootid(第一个选项可能更好,第二个选项主要适用于创建某种根视图的情况)

with RecursiveQuery 
AS
(
    SELECT a.ParentID theID, a.ParentID RootID
    FROM  [LessonCategory] AS a    
    UNION ALL
    SELECT b.CategoryID, d.RootID
    FROM [LessonCategory] AS b
    INNER JOIN RecursiveQuery AS d
        ON d.theID = b.ParentID
)
SELECT theID from RecursiveQuery where RootID = 3