2009-07-14 64 views
2

既然我有这个结果集的结构(多余领域已剥离)SQL服务器树层次结构,并与重复记录ID嵌套集合

Id | ParentId | Name | Depth 
---------------------------- 

是有可能有记录在树的顺序返回即Parent然后Children ,如果ChildParent,那么他们的Children,如果不是那么Sibling等?例如,

Id | ParentId | Name | Depth 
---------------------------- 
1 NULL  Major 1 
2 1   Minor 2 
3 1   Minor 2 
4 3   Build 3 
5 3   Build 3 
6 1   Minor 2 

/* etc, etc */ 

,我能想到这样做的唯一方法是按照本文 -

Improve hierarchy performance using nested sets

,包括对每个记录[LeftExtent][RightExtent]领域。现在,当Ids是唯一的时候,文章中的SQL可以正常工作,但在这个特定的树结构中,具有相同Id的记录可以出现在树中的不同位置(显然,ParentId字段不同)。我认为这个问题是从文章这个SQL -

INSERT INTO @tmpStack 
    (
     EmployeeID, 
     LeftExtent 
    ) 
    SELECT TOP 1 EmployeeID, @counter 
    FROM Employee 
    WHERE ISNULL(ParentID, 0) = ISNULL(@parentid,0) 
    /* If the Id has already been added then record is not given [LeftExtent] or [RightExtent] values. */ 
    AND EmployeeID NOT IN (SELECT EmployeeID FROM @tmpStack) 

这怎么可能改变,以允许给具有重复Ids记录[LeftExtent]和[RightExtent]值,或我完全缺少一个更简单的方法以我需要的顺序返回结果集?

回答

6

这里有一个做的伎俩对我来说:

@ParentID只是在层次结构的起点,但你可以在0传递(但我认为你正在使用null作为基地ID,所以你会明白)

有序排序的关键是与建立的排序关键。

WITH RoleHierarchy (RoleID, [Role], [Description], ParentID, Editable, HierarchyLevel, SortKey) AS 
(
    -- Base 
    SELECT 
     RoleID, 
     [Role], 
     [Description], 
     ParentID, 
     Editable, 
     0 as HierarchyLevel, 
     CAST(RoleID AS VARBINARY(300)) 
    FROM 
     dbo.Roles  
    WHERE 
     RoleID = @ParentID 

    UNION ALL 

    -- Recursive 
    SELECT 
     e.RoleID, 
     e.[Role], 
     e.[Description], 
     e.ParentID, 
     e.Editable, 
     th.HierarchyLevel + 1 AS HierarchyLevel, 
     CAST (th.SortKey + CAST (e.[Role] AS VARBINARY(100)) + CAST (e.[RoleID] AS VARBINARY(100)) AS VARBINARY(300)) 
    FROM 
     Roles e 
     INNER JOIN RoleHierarchy th ON e.ParentID = th.RoleID 
    WHERE 
     e.RoleID != 0 
) 

SELECT 
    RoleID, 
    ParentID, 
    [Role], 
    [Description], 
    Editable, 
    HierarchyLevel 
FROM 
    RoleHierarchy 
WHERE 
    RoleID != @ParentID 
ORDER BY 
    SortKey 
+0

结果集的测试表明这个效果很好:) – 2009-07-14 15:10:30

+0

好吧,让我知道如果你注意到任何奇怪的东西,我已经使用了一段时间! – ScottE 2009-07-14 16:56:05

2

您应该在SQL Server 2005中看看递归公用表表达式:

在你的情况,这将是这样的:

WITH EmployeeCTE AS 
(
    -- get the anchor 
    SELECT ID, ParentID, Name, 0 as 'Depth' 
    FROM Employee WHERE ParentID IS NULL 

    -- recursively union lower levels 
    UNION ALL 
    SELECT e.ID, e.ParentID, e.Name, e.Depth+1 
    FROM Employee e 
    INNER JOIN EmployeeCTE ON e.ParentID = EmployeeCTE.ID 
) 
SELECT * FROM EmployeeCTE 

这应该给你一个很好的查询结果集与吨他正在寻找的数据。或者我错过了什么?

马克

+0

我有一个CTE目前递归加入记录来构建结果集。这工作正常,但问题是结果集中的记录顺序不是我想要的问题中指定的顺序。我将修改问题来说明结果集结构,而不是表结构 – 2009-07-14 11:18:30