2011-04-13 23 views
7

Tengo un problema que no puedo entender. Sé lo que quiero, simplemente no puedo sacarlo en la pantalla. Lo que tengo es una mesa con este aspecto:Selección recursiva en SQL

Id, PK UniqueIdentifier, NotNull 
Name, nvarchar(255), NotNull 
ParentId, UniqueIdentifier, Null 

parentid tiene una FK a Id.

Lo que quiero lograr es conseguir una lista plana de todos los identificadores por debajo del Id yo paso en

ejemplo:.

1 TestName1 NULL 
2 TestName2 1 
3 TestName3 2 
4 TestName4 NULL 
5 TestName5 1 

El árbol se vería así:

-1 
    -> -2 
     -> -3 
    -> -5 
-4 

Si ahora pido 4, solo obtendría 4 de vuelta, pero si pido 1 obtendría 1, 2, 3 y 5. Si solicito 2, obtendría 2 y 3, y así sucesivamente .

¿Hay alguien que pueda señalarme en la dirección correcta? Mi cerebro está frito así que agradezco toda la ayuda que pueda obtener.

Respuesta

12
declare @T table(
    Id int primary key, 
    Name nvarchar(255) not null, 
    ParentId int) 

insert into @T values 
(1, 'TestName1', NULL), 
(2, 'TestName2', 1), 
(3, 'TestName3', 2), 
(4, 'TestName4', NULL), 
(5, 'TestName5', 1) 

declare @Id int = 1 

;with cte as 
( 
    select T.* 
    from @T as T 
    where T.Id = @Id 
    union all 
    select T.* 
    from @T as T 
    inner join cte as C 
     on T.ParentId = C.Id 
) 
select * 
from cte  

Resultado

Id   Name     ParentId 
----------- -------------------- ----------- 
1   TestName1   NULL 
2   TestName2   1 
5   TestName5   1 
3   TestName3   2 
+1

Esta es la forma en que lo haría, repitiendo Abajo el árbol desde el nodo que se está buscando. – MatBailie

+0

¡Esto funciona genial! parece ser rápido y lograr justo lo que quiero. ¡Muchas gracias por la ayuda! Finalmente me vuelvo a encontrar :) – MrW

+0

@Dems +1. ¡Volver a bajar es lo que quiero! :) – MrW

0

Aquí hay un buen artículo sobre Hierarchy ID models. Va directamente desde el inicio de los datos hasta los diseños de consulta.

Además, podría usar un Recursive Query using a Common Table Expression.

+0

Vale la pena mencionar que el primer artículo se vincula a realmente utiliza expresiones de tabla comunes para consultas recursivas (a pesar de que no sale y menciona el hecho). –

0

Prueba esto:

WITH RecQry AS 
(
    SELECT * 
     FROM MyTable 
    UNION ALL 
    SELECT a.* 
     FROM MyTable a INNER JOIN RecQry b 
     ON a.ParentID = b.Id 
) 
SELECT * 
    FROM RecQry 
3

Aquí está un ejemplo de trabajo:

declare @t table (id int, name nvarchar(255), ParentID int) 

insert @t values 
(1, 'TestName1', NULL), 
(2, 'TestName2', 1 ), 
(3, 'TestName3', 2 ), 
(4, 'TestName4', NULL), 
(5, 'TestName5', 1 ); 

; with rec as 
     (
     select t.name 
     ,  t.id as baseid 
     ,  t.id 
     ,  t.parentid 
     from @t t 
     union all 
     select t.name 
     ,  r.baseid 
     ,  t.id 
     ,  t.parentid 
     from rec r 
     join @t t 
     on  t.ParentID = r.id 
     ) 
select * 
from rec 
where baseid = 1 

puedes realizar un filtrado sobre baseid, que contiene el inicio del árbol que está consultando.

+0

Esto reafirma el árbol, para todo el árbol, luego filtra los registros deseados. ¿No es 'mejor' comenzar en el nodo requerido y luego recurse hacia abajo? – MatBailie

+0

@Dems: el optimizador moverá la cláusula where al CTE, por lo que se ejecutará como sugiera. Parecía más claro mover la condición de inicio fuera de la maquinaria recursiva. – Andomar

+0

Disculpas, leed mal, esto sí que se repite en el árbol, por lo que la cláusula DONDE sí previene la calcualción inecesaria. – MatBailie

Cuestiones relacionadas