给定一个带有hierarchyid
类型列的表,如何编写查询以返回作为特定节点的祖先的所有行?如何获得使用SQL Server 2008 hierarchyid的节点的所有祖先?
有一个IsDescendantOf()
功能,这是完美的让孩子,但没有相应IsAncestorOf()
函数返回的祖先(和缺乏GetAncestors()
功能恍如很大的一个疏忽。)
给定一个带有hierarchyid
类型列的表,如何编写查询以返回作为特定节点的祖先的所有行?如何获得使用SQL Server 2008 hierarchyid的节点的所有祖先?
有一个IsDescendantOf()
功能,这是完美的让孩子,但没有相应IsAncestorOf()
函数返回的祖先(和缺乏GetAncestors()
功能恍如很大的一个疏忽。)
最常用的方法是一个递归公用表表达式(CTE)
WITH Ancestors(Id, [Name], AncestorId) AS
(
SELECT
Id, [Name], Id.GetAncestor(1)
FROM
dbo.HierarchyTable
WHERE
Name = 'Joe Blow' -- or whatever you need to select that node
UNION ALL
SELECT
ht.Id, ht.[Name], ht.Id.GetAncestor(1)
FROM
dbo.HierarchyTable ht
INNER JOIN
Ancestors a ON ht.Id = a.AncestorId
)
SELECT *, Id.ToString() FROM Ancestors
(改编自Simon Ince blog post)
西蒙·因斯也建议他基本上只是反转条件的第二种方法 - 而不是检测是目标的人的祖先,那些人的条目,他转身检查:
DECLARE @person hierarchyid
SELECT @person = Id
FROM dbo.HierachyTable
WHERE [Name] = 'Joe Blow';
SELECT
Id, Id.ToString() AS [Path],
Id.GetLevel() AS [Level],
Id.GetAncestor(1),
Name
FROM
dbo.HierarchyTable
WHERE
@person.IsDescendantOf(Id) = 1
这将选择所有从表中的行,你感兴趣的目标人是下一级的任何级别的后代。所以这会发现目标人的直接和非直接的祖先一直到根。
这里有一个答案卷起成一个单一的选择:
SELECT t1.Id.ToString() as Path, t1.Name
FROM (SELECT * FROM HierarchyTable
WHERE Name = 'Joe Blow') t2,
HierarchyTable t1
WHERE t2.Id.IsDescendantOf(t1.Id) = 1
where子句的第一个谓词是多余的,因为父类始终是它自己的后代。 http://msdn.microsoft.com/en-us/library/bb677203(v=sql.105).aspx – influent 2014-12-17 17:53:59
Declare @hid hierarchyid=0x5D10 -- Child hierarchy id
SELECT
*
FROM
dbo.TableName
WHERE
@hid.IsDescendantOf(ParentHierarchyId) = 1
即使您在hierarchyID上有一个索引,它也必须为每一行评估IsDesendentOf,否?我想我有更好的办法(看我的回答) – 2016-02-14 01:48:22
我写了一个扩展值HIERARCHYID成其组成祖先用户定义的表值函数。然后可以将输出重新连接到hierarchyid列以专门获取这些祖先。
alter function dbo.GetAllAncestors(@h hierarchyid, @ReturnSelf bit)
returns table
as return
select @h.GetAncestor(n.Number) as h
from dbo.Numbers as n
where n.Number <= @h.GetLevel()
or (@ReturnSelf = 1 and n.Number = 0)
union all
select @h
where @ReturnSelf = 1
go
去了解使用它:
select child.ID, parent.ID
from dbo.yourTable as child
cross apply dbo.GetAllAncestors(child.hid, 1) as a
join dbo.yourTable as parent
on parent.hid = a.h
请帮我解决这个问题。 http://stackoverflow.com/questions/44016261/how-do-you-get-recursivelevel-using-sql-server-2012-hierarchyid – ManojKanth 2017-05-17 05:36:44
是不是'child.IsDescendantOf(父)'一样'parent.IsAncestorOf(孩子)'? – Gabe 2010-06-25 17:18:24