我有一个带有ID的基本sql表和来自同一个表的可选parentID。这有多个级别。我需要获得所有ID的列表,其中每个父母一直到顶部。
ID | Name | ParentID
_______________________
1 John null
2 Doe 1
3 Mike 1
4 Neil 3
5 Sylvia 4
6 Mary 2
我需要得到一个这样的列表:
ID | Parent | DirectParent
_______________________
2 1 1
3 1 1
4 3 1
4 1 0
5 4 1
5 3 0
5 1 0
如何查询上表以获取此数据?
答案 0 :(得分:2)
递归CTE将在这里完成工作。最棘手的部分是获取直接父位列,希望我从预期结果中正确理解逻辑。作为奖励,我为所有可能的路径添加了实际的报告层次结构列。 (此处递归深度最多为10次)
CREATE TABLE #MyTable
(
ID int primary key,
Name nvarchar (max),
ParentID int
)
INSERT INTO #MyTable
Values (1, 'John', null),
(2, 'Doe', 1),
(3, 'Mike', 1),
(4, 'Neil', 3),
(5, 'Sylvia', 4),
(6, 'Mary', 2)
WITH FindRoot AS
(
SELECT ID, ParentId, ParentId as Parent, CAST(Name AS NVARCHAR(MAX)) Path, 0 Distance
FROM #MyTable
UNION ALL
SELECT P.ID, p.ParentId, c.Parent, C.Path + N' > ' + CAST(Name AS NVARCHAR(MAX)), C.Distance + 1
FROM #MyTable P
JOIN FindRoot C
ON C.ID = P.ParentId AND P.ParentId <> P.ID and C.ParentId <> c.ID
WHERE C.DISTANCE < 10
)
SELECT R.ID, R.Parent,
CASE WHEN R1.Parent IS NULL THEN 1
ELSE 0
END AS DirectParent, R.Path as ReportingHierarchy
FROM FindRoot R
LEFT JOIN FindRoot R1 on R1.ID = R.ID and R1.Parent =
(SELECT Top 1 Parent From FindRoot
WHERE ID = R.ID and Parent > R.Parent
Order by Parent)
WHERE R.Distance >= 0 and R.ParentId is not null
Order by R.ID, R.distance
option(maxrecursion 10)
结果如下:
+----+--------+--------------+----------------------+
| ID | Parent | DirectParent | ReportingHierarchy |
+----+--------+--------------+----------------------+
| 2 | 1 | 1 | Doe |
| 3 | 1 | 1 | Mike |
| 4 | 3 | 1 | Neil |
| 4 | 1 | 0 | Mike > Neil |
| 5 | 4 | 1 | Sylvia |
| 5 | 3 | 0 | Neil > Sylvia |
| 5 | 1 | 0 | Mike > Neil > Sylvia |
| 6 | 2 | 1 | Mary |
| 6 | 1 | 0 | Doe > Mary |
+----+--------+--------------+----------------------+
修改强>
应该提到这一点,但根据对此答案的评论 - 确保您已将ParentID
和ID
列编入索引。