鉴于我有这个结果集结构(多余的字段已被剥离)
Id | ParentId | Name | Depth
----------------------------
是否可以按树顺序返回记录,即Parent
然后Children
,如果Child
是Parent
,那么他们的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]值,或者我完全错过了以我需要的顺序返回结果集的更简单方法? / p>
答案 0 :(得分: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
答案 1 :(得分:3)
您应该查看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
这应该为您提供一个很好的查询结果集,其中包含您正在寻找的数据。或者我错过了什么?
马克
答案 2 :(得分:0)
如果您使用materialized path或HIERARCHYID,那么生活会更容易......