2011-04-02 17 views
10

tengo una mesa con estructura de árbol:consulta SQL para la tabla del árbol

id parentId name 
---------------- 
1 0  Category1 
2 0  Category2 
3 1  Category3 
4 2  Category4 
5 1  Category5 
6 2  Category6 
7 3  Category7 

En resut consulta SQL que necesita una tabla como:

id parentId level name 
---------------------- 
1 0  0  Category1 
3 1  1  Category3 
7 3  2  Category7 
5 1  1  Category5 
2 0  0  Category2 
4 2  1  Category4 
6 2  1  Category6 

¿Quién puede ayudar a mí escribir ms-sql consulta ? Gracias!

Respuesta

16

Ampliando la respuesta de a_horse_with_no_name, esta muestra cómo utilizar de SQL Server implementation of recursive CTE (Recursive single-record cross apply) en combinación con row_number() para producir el resultado exacto en la pregunta.

declare @t table(id int,parentId int,name varchar(20)) 
insert @t select 1, 0  ,'Category1' 
insert @t select 2, 0,  'Category2' 
insert @t select 3, 1,  'Category3' 
insert @t select 4 , 2,  'Category4' 
insert @t select 5 , 1,  'Category5' 
insert @t select 6 , 2,  'Category6' 
insert @t select 7 , 3,  'Category7' 
; 

WITH tree (id, parentid, level, name, rn) as 
(
    SELECT id, parentid, 0 as level, name, 
     convert(varchar(max),right(row_number() over (order by id),10)) rn 
    FROM @t 
    WHERE parentid = 0 

    UNION ALL 

    SELECT c2.id, c2.parentid, tree.level + 1, c2.name, 
     rn + '/' + convert(varchar(max),right(row_number() over (order by tree.id),10)) 
    FROM @t c2 
    INNER JOIN tree ON tree.id = c2.parentid 
) 
SELECT * 
FROM tree 
order by RN 

Para ser sinceros, utilizando los mismos identificadores para producir el "camino" árbol funcionaría, ya que estamos pidiendo directamente por id, pero pensé que había un desliz en la función row_number().

19
WITH tree (id, parentid, level, name) as 
(
    SELECT id, parentid, 0 as level, name 
    FROM your_table 
    WHERE parentid = 0 

    UNION ALL 

    SELECT c2.id, c2.parentid, tree.level + 1, c2.name 
    FROM your_table c2 
    INNER JOIN tree ON tree.id = c2.parentid 
) 
SELECT * 
FROM tree 

que tienen actualmente ninguna de SQL Server a la mano para probarlo, por lo que puede haber algunos errores tipográficos (errores de sintaxis) en allí

+0

Es perfecto. Pero consulte "Editar - información" en [esta respuesta] (http://stackoverflow.com/questions/5416512/recursive-cte-with-ranking-functions/5417257#5417257). Su consulta muestra la salida en orden de registro inverso, primero en profundidad. OP necesita el orden exacto como se muestra? – RichardTheKiwi

+0

@Andomar: ¿por qué agregaste el punto y coma innecesario? Estoy bastante seguro de que funciona sin (nunca he puesto un punto y coma en la * fachada * de una declaración, me parece bastante extraño) –

+1

@a_horse_with_no_name - Uno de los pocos lugares en que se requiere un semi-punto en SQL Server es en declaración que precede al 'CON 'por lo que este es un modismo bastante común. Normalmente también lo hago en mis respuestas para anticipar el OP pegándolo en código existente que no termina con un punto y medio y obteniendo un error de "sintaxis incorrecta". –

Cuestiones relacionadas