transact tabla query jerarquica ejemplo sql-server hierarchyid

sql-server - tabla - transact sql hierarchy



¿Cómo se obtienen todos los ancestros de un nodo con SQL Server 2008 hierarchyid? (4)

Dada una tabla con una columna de tipo hierarchyid , ¿cómo se escribe una consulta para devolver todas las filas que son ancestros de un nodo específico?

Hay una función IsDescendantOf() que es perfecta para obtener los hijos, pero no hay una función correspondiente IsAncestorOf() para devolver antepasados ​​(y la ausencia de una función GetAncestors() parece ser un descuido).


Aquí hay una respuesta enrollada en una sola selección:

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


El enfoque más comúnmente utilizado sería una expresión de tabla común (CTE) recursiva

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

(Adaptado de un post de Simon Ince )

Simon Ince también propone un segundo enfoque en el que básicamente invierte la condición; en lugar de detectar esas entradas de personas que son un antepasado de la persona objetivo, él revierte la verificación:

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

Esto seleccionará todas las filas de su tabla, donde la persona objetivo que le interesa es un descendiente de cualquier nivel en la jerarquía. Así que esto encontrará a los ancestros inmediatos y no inmediatos de la persona objetivo hasta la raíz.


Escribí una función de valor de tabla definida por el usuario que expande un valor de jerarquía en sus ancestros constituyentes. La salida se puede unir de nuevo en la columna hierarchyid para obtener esos ancestros específicamente.

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

Para utilizarlo:

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


Declare @hid hierarchyid=0x5D10 -- Child hierarchy id SELECT * FROM dbo.TableName WHERE @hid.IsDescendantOf(ParentHierarchyId) = 1