递归查询 SQL 服务器未按预期工作

Recursive query SQL Server not working as expected

在此先感谢您的帮助。我对 MS SQL db 还是很陌生,但我想知道为什么我对下面的 MSSQL 的递归查询没有 return 我期望的值。我已经完成了研究,底部是我想出的代码。假设我有以下 table...

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

我期待下面的查询 return 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

如果你想要来自特定根的树:

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

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

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(第一个选项可能更好,第二个主要适用于创建某种root-view的情况)

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