递归Linq或Sql查询以获取自引用表中每个类别的最顶层父级

时间:2012-05-07 17:24:25

标签: sql-server-2008 tsql linq-to-sql linq-to-entities

e.g。如果我有一个如下表: -

    create table Categories(CategoryId int primary key,
 ParentCategoryId int foreign key references Categories(CategoryId))

例如,如果我的表中有以下数据: -

CategoryID  ParentCategoryId
1           2
2           3
3           4
4           NULL
5           6
6           7
7           NULL
8           9
9           NULL

Result:     

CategoryId  ParentCategoryId
1           4
2           4
3           4
4           NULL
5           7
6           7
7           NULL
8           9
9           NULL

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

在SQL中你可以这样做:

DECLARE @childId int
SET @childId = 1

DECLARE @nextId int
DECLARE @currentId int

SET @nextId = @childId

WHILE (NOT (@nextId IS NULL))
BEGIN
    SET @currentId = @nextId

    SELECT @nextId = ParentCategoryId
    FROM Categories
    WHERE CategoryId = @currentId
END

SELECT @currentId AS RootCategoryId

在Linq,你正在寻找类似的东西:

public int GetRootCategoryId(int childId)
{
    int? nextId = childId
    int? currentID;

    while (nextID != null)
    {
        currentID = nextID;
        nextID = (from category in db.Categories
                 where category.CategoryId = currentID
                 select category.ParentCategoryId).First();
    }

    return currentID;
}

答案 1 :(得分:1)

CREATE TABLE #Parents (CategoryID INT PRIMARY KEY, ParentCategoryID INT)
INSERT #Parents
SELECT *
FROM Categories
WHILE @@ROWCOUNT != 0 BEGIN
    UPDATE p
    SET p.ParentCategoryID = c.ParentCategoryID
    FROM #Parents p
    JOIN Categories c ON p.ParentCategoryID = c.CategoryID
    WHERE c.ParentCategoryID IS NOT NULL
END
SELECT *
FROM #Parents
ORDER BY 1
DROP TABLE #Parents

答案 2 :(得分:1)

这是递归CTE解决方案。可能更优雅高效?

WITH TopLevelParents AS (
    SELECT CategoryID, ParentCategoryID
    FROM Categories
    WHERE ParentCategoryID IS NULL
    UNION ALL
    SELECT c.CategoryID, ISNULL(p.ParentCategoryID, p.CategoryID) ParentCategoryID
    FROM Categories c
    JOIN TopLevelParents p ON c.ParentCategoryID = p.CategoryID
)
SELECT *
FROM TopLevelParents
ORDER BY 1