SQL Server树层次结构和具有重复记录ID的嵌套集

Rus*_*Cam 3 sql sql-server tree sql-server-2005 nested-sets

鉴于我有这个结果集结构(多余的字段已被剥离)

Id | ParentId | Name | Depth
----------------------------
Run Code Online (Sandbox Code Playgroud)

是有可能有树的顺序返回即记录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 */
Run Code Online (Sandbox Code Playgroud)

我能想到这样做的唯一方法就是遵循这篇文章 -

使用嵌套集提高层次结构性能

并包含每个记录的字段[LeftExtent][RightExtent]字段.现在文章中的SQL在Ids唯一时工作正常,但在这个特定的树结构中,具有相同记录的记录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) 
Run Code Online (Sandbox Code Playgroud)

如何更改以允许具有重复的记录Ids被赋予[LeftExtent]和[RightExtent]值,或者我完全错过了以我需要的顺序返回结果集的更简单方法?

Sco*_*ttE 7

这是为我做的诀窍:

@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
Run Code Online (Sandbox Code Playgroud)