我有以下两个表
餐 table 上的人
Id Name
1 A
2 B
3 C
4 D
5 E
表关系层次结构
ParentId CHildId
2 1
3 2
4 3
这将形成一个树状结构
D
|
C
|
B
|
A
ParentId和ChildId是Person表的Id列的外键
我需要编写可以获取我的顶级父级(即每个人的根)的 SQL。
以下 CTE 可以为 Each 执行此操作。我将其转换为函数并为每一行 Person 运行它。我在 Person 表中有大约 3k 行,大约需要 10 秒才能完成。任何人都可以建议一种可以减少花费的方法。问题是在 CTE 运行 3k 次之后运行的函数
DECLARE @childID INT
SET @childID = 1 --chield to search
;WITH RCTE AS
(
SELECT *, 1 AS Lvl FROM RelationHierarchy
WHERE ChildID = @childID
UNION ALL
SELECT rh.*, Lvl+1 AS Lvl FROM dbo.RelationHierarchy rh
INNER JOIN RCTE rc ON rh.CHildId = rc.ParentId
)
SELECT TOP 1 id, Name
FROM RCTE r
inner JOIN dbo.Person p ON p.id = r.ParentId
ORDER BY lvl DESC
最佳答案
我还更新了 original question 中的答案,但没关系,这里还有一份副本:
;WITH RCTE AS
(
SELECT ParentId, ChildId, 1 AS Lvl FROM RelationHierarchy
UNION ALL
SELECT rh.ParentId, rc.ChildId, Lvl+1 AS Lvl
FROM dbo.RelationHierarchy rh
INNER JOIN RCTE rc ON rh.ChildId = rc.ParentId
)
,CTE_RN AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY r.ChildID ORDER BY r.Lvl DESC) RN
FROM RCTE r
)
SELECT pc.Id AS ChildID, pc.Name AS ChildName, r.ParentId, pp.Name AS ParentName
FROM dbo.Person pc
LEFT JOIN CTE_RN r ON pc.id = r.CHildId AND RN =1
LEFT JOIN dbo.Person pp ON pp.id = r.ParentId
<强> SQLFiddle DEMO
请注意,细微的差别在于 CTE 的递归部分。现在每次从 anchor 部分重写 ChildID。另外还添加了 ROW_NUMBER() 函数(和新的 CTE),用于在最后获取每个子级的顶层。
编辑 - 版本 2
在发现第一个查询的性能问题后,这里有一个改进的版本。从上到下,而不是其他方式 - 消除在 CTE 中创建额外的行,在大量递归上应该更快:
;WITH RCTE AS
(
SELECT ParentId, CHildId, 1 AS Lvl FROM RelationHierarchy r1
WHERE NOT EXISTS (SELECT * FROM RelationHierarchy r2 WHERE r2.CHildId = r1.ParentId)
UNION ALL
SELECT rc.ParentId, rh.CHildId, Lvl+1 AS Lvl
FROM dbo.RelationHierarchy rh
INNER JOIN RCTE rc ON rc.CHildId = rh.ParentId
)
SELECT pc.Id AS ChildID, pc.Name AS ChildName, r.ParentId, pp.Name AS ParentName
FROM dbo.Person pc
LEFT JOIN RCTE r ON pc.id = r.CHildId
LEFT JOIN dbo.Person pp ON pp.id = r.ParentId
<强> SQLFiddle DEMO
关于sql - 查找表中每一行的顶级父级 [SQL Server 2008],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17703863/