2012-07-22 10 views
12

Dado un identificador hijo, necesito devolver una consulta que contenga todos los padres de ese niño y sus padres hasta que llegue al padre raíz. Por ejemplo, teniendo en cuenta estos datos:Buscar recursivamente todos los antepasados ​​dados al niño

ID/Parent ID 
1/0 
2/1 
3/2 
4/0 
5/3 

Así que si pasaba en ID 5 Me gustaría obtener una consulta con los resultados:

ID/Parent ID 
1/0 
2/1 
3/2 

Esta tabla no funciona con un tipo hierarchyid por lo Sospecho que esto tendrá que hacerse con un CTE, pero no tengo idea de cómo. Si se puede hacer en una consulta SQL/proc, cualquier ayuda sería apreciada.

Gracias

Respuesta

20

Esto es más o menos lo que quiere:

-- CTE to prepare hierarchical result set 
;WITH #results AS 
(
    SELECT id, 
      parentid 
    FROM [table] 
    WHERE id = @childId 
    UNION ALL 
    SELECT t.id, 
      t.parentid 
    FROM [table] t 
      INNER JOIN #results r ON r.parentid = t.id 
) 
SELECT * 
FROM #results; 

Referencia:

Ejemplo de trabajo:

-- create table with self lookup (parent id) 
CREATE TABLE #tmp (id INT, parentid INT); 

-- insert some test data 
INSERT INTO #tmp (id, parentid) 
SELECT 1,0 UNION ALL SELECT 2,1 UNION ALL SELECT 3,2 
UNION ALL SELECT 4,0 UNION ALL SELECT 5,3; 

-- prepare the child item to look up 
DECLARE @childId INT; 
SET @childId = 5; 

-- build the CTE 
WITH #results AS 
(
    SELECT id, 
      parentid 
    FROM #tmp 
    WHERE id = @childId 
    UNION ALL 
    SELECT t.id, 
      t.parentid 
    FROM #tmp t 
      INNER JOIN #results r ON r.parentid = t.id 
) 

-- output the results 
SELECT * 
FROM #results 
WHERE id != @childId 
ORDER BY id; 

-- cleanup 
DROP TABLE #tmp; 

Salida:

1 | 0
2 | 1
3 | 2

+0

Esto es simplemente increíble. El único cambio que hice fue usar la cláusula DISTINCT en el SELECT final. No me preocupa el rendimiento debido a los pequeños conjuntos de registros con los que trabajaré. Esto filtra los duplicados y simplemente devuelve las jerarquías que quiero, de acuerdo con los criterios que puse en la cláusula WHERE de la primera consulta CTE (no usando id = @childId en mi caso) – bcr

Cuestiones relacionadas