El más utilizado enfoque sería una expresión recursiva de tabla comunes (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
(adaptado de un Simon Ince blog post)
Simon Ince también propone un segundo enfoque en el que, básicamente, sólo invierte el estado - en lugar de detectar esas entradas de personas que son un antepasado de la persona objetivo, se da el cheque en torno a:
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 la tabla, donde la persona objetivo que le interesa es descendiente de cualquier nivel de la jerarquía. De modo que esto encontrará los ancestros inmediatos y no inmediatos de la persona objetivo hasta la raíz.
no es 'child.IsDescendantOf (padre)' 'lo mismo que parent.IsAncestorOf (niño)'? – Gabe