2009-05-12 8 views

risposta

8

Utilizzare CTE.

Data l'albero-come la struttura della tabella:

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 

, questa query restituirà id, parent e la profondità di livello, ordinato come un albero:

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 

Sostituire parent = 0 con parent = @parent per ottenere solo un ramo di un albero.

Se esiste un indice su table (parent), questa query funzionerà in modo efficiente su una tabella molto grande, poiché utilizzerà ricorsivamente INDEX LOOKUP per trovare tutti i chilrden per ciascun genitore.

Per aggiornare un ramo certo problema:

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 
     ) 

dove @parent è la radice del ramo.

+0

Potete per favore elaborare la struttura dei tavoli? questa query funzionerà bene con un db di grandi dimensioni? – SirMoreno

+0

grazie, Come si può fare un aggiornamento approfondito? - aggiorna tutti i nodi sotto un genitore? (Compresi i nipoti) – SirMoreno

+0

ehi, sto cercando di farlo funzionare, e sembra che l'elemento VQ dosent lavoro, sto provando nel 2008 però.Inoltre, il livello deve essere memorizzato nel database, in quanto non è mostrato nella tabella? –

2

Verificare Joe Celko's book on trees and hierarchies per diversi modi per affrontare il problema della gerarchia. Il modello che scegli dipenderà da come pesi le ricerche rispetto agli aggiornamenti rispetto alla complessità. È possibile rendere le ricerche abbastanza rapide (soprattutto per ottenere tutti i bambini in un nodo) utilizzando il modello di elenco di adiacenza, ma gli aggiornamenti alla struttura sono più lenti.

+0

Grazie, cercherò. L'unione è più efficiente del ricorsivo? Ho sentito che mssql 2005 ha un nuovo modo di gestire gli alberi, sai se funziona bene con DB di grandi dimensioni? – SirMoreno

+0

L'UNION ALL all'interno di un CTE è ricorsivo, anche se non sono sicuro di come SQL Server lo gestisca dietro le quinte o se ci sono ritocchi delle prestazioni ad esso. Non ho fatto abbastanza test su larga scala con CTE per dire con certezza sulle prestazioni. –

3

È necessario porsi queste domande prima: 1) Qual è il rapporto tra le modifiche e le letture? (= albero per lo più statico o in costante cambiamento?) 2) Quanto profondo e quanto ti aspetti che l'albero cresca?

I set nidificati sono ideali per gli alberi per lo più statici in cui è necessario eseguire operazioni su interi rami. Gestisce alberi profondi senza problemi.

materializzata percorso funziona bene per dinamico (cambia) alberi vincolata profondità/prevedibile.

CTE recursive sono l'ideale per molto piccoli alberi, ma le operazioni di filiale ("ottenere tutti i bambini in questo ramo ..") ottenere molto costosi con profonda grande albero /.

+1

My Tree è molto dinamico, molti aggiornamenti ma molti selezionano pure. E mi piacerebbe essere in grado di approfondire come 10-15 livelli. Ho trovato questo articolo sui set annidati: http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/swinging-from-tree-to-tree-using-ctes-part-1-adjacency -to-nested-sets.aspx I set nidificati come descritto in questo articolo sono la mia migliore opzione? grazie. – SirMoreno

0

Mi sorprende che nessuno ha menzionato andando con un Closure Table . Molto efficiente per letture e molto semplice da scrivere.