2009-05-12 15 views

Respuesta

8

Use CTE 's.

Dada la estructura de la tabla en forma de árbol:

id parent name 
1 0  Electronics 
2 1  TV 
3 1  Hi-Fi 
4 2  LCD 
5 2  Plasma 
6 3  Amplifiers 
7 3  Speakers 

, esta consulta devolverá id, parent y la profundidad de nivel, ordenados como un árbol:

WITH v (id, parent, level) AS 
     (
     SELECT id, parent, 1 
     FROM table 
     WHERE parent = 0 
     UNION ALL 
     SELECT id, parent, v.level + 1 
     FROM v 
     JOIN table t 
     ON  t.parent = v.id 
     ) 
SELECT * 
FROM v 

id parent name 
1 0  Electronics 
2 1  TV 
4 2   LCD 
5 2   Plasma 
3 1  Hi-Fi 
6 3   Amplifiers 
7 3   Speakers 

Reemplazar parent = 0 con parent = @parent para conseguir solamente una rama de un árbol.

Siempre que haya un índice en table (parent), esta consulta funcionará eficientemente en una tabla muy grande, ya que usará recursivamente INDEX LOOKUP para encontrar todos los chilrden para cada padre.

Para actualizar una rama determinada, ejecuta:

WITH v (id, parent, level) AS 
     (
     SELECT id, parent, 1 
     FROM table 
     WHERE parent = 0 
     UNION ALL 
     SELECT id, parent, v.level + 1 
     FROM v 
     JOIN table t 
     ON  t.parent = v.id 
     ) 
UPDATE table t 
SET  column = newvalue 
WHERE t.id IN 
     (
     SELECT id 
     FROM v 
     ) 

donde @parent es la raíz de la rama.

+0

¿Puede explicar la estructura de las tablas? ¿Esta consulta funcionará bien con un db grande? – SirMoreno

+0

gracias, ¿Cómo puedo hacer una actualización profunda? - actualizar todos los nodos bajo un padre? (incluyendo a los nietos) – SirMoreno

+0

hey, estoy tratando de hacer que esto funcione, y parece que el trabajo de dosent de vq funciona, lo estoy intentando en 2008.Además, ¿el nivel debe almacenarse en la base de datos, ya que no se muestra en la tabla? –

2

Consulte Joe Celko's book on trees and hierarchies para conocer múltiples formas de abordar el problema de la jerarquía. El modelo que elija dependerá de cómo pondere las búsquedas frente a las actualizaciones frente a la complejidad. Puede hacer las búsquedas bastante rápido (especialmente para obtener todos los elementos secundarios en un nodo) utilizando el modelo de lista de adyacencia, pero las actualizaciones del árbol son más lentas.

+0

Gracias lo buscaré. ¿La unión es más eficiente que la recursiva? He oído que mssql 2005 tiene una nueva forma de tratar con árboles, ¿sabe si funciona bien con grandes DB? – SirMoreno

+0

El UNION ALL dentro de un CTE es recursivo, aunque no estoy seguro de cómo SQL Server lo maneja detrás de escena o si hay ajustes de rendimiento en él. No he realizado suficientes pruebas a gran escala con CTE para asegurar mi rendimiento. –

3

Primero tiene que hacerse estas preguntas: 1) ¿Cuál es la proporción de modificaciones frente a lecturas? (= mayormente árbol estático o cambiando constantemente?) 2) ¿Qué tan profundo y qué tan grande esperas que crezca el árbol?

Los juegos anidados son ideales para árboles en su mayoría estáticos donde se necesitan operaciones en ramas enteras. Maneja árboles profundos sin problemas.

La trayectoria materializada funciona bien para árboles dinámicos (cambiantes) con profundidad limitada/predecible.

Los CTE recursivos son ideales para árboles muy pequeños, pero las operaciones de bifurcación ("obtener todos los niños en esta rama ...") se vuelven muy costosas con árboles grandes/profundos.

+1

My Tree es muy dinámico, muchas actualizaciones pero muchas selecciones también. Y me gustaría poder profundizar en 10-15 niveles. Encontré este artículo sobre conjuntos anidados: http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/swinging-from-tree-to-tree-using-ctes-part-1-adjacency -to-nested-sets.aspx ¿Serán los conjuntos anidados como los descritos en este artículo mi mejor opción? gracias. – SirMoreno

0

Me sorprende que nadie ha mencionado ir con un Closure Table . Muy eficiente para leer y bastante simple de escribir.

Cuestiones relacionadas