Dati questi vincoli, non c'è modo. In tal caso, potresti recuperare tutto l'albero e costruire un lato client "collinare", oppure eseguire query ricorsive, qualunque cosa sarebbe più performante nel caso specifico.
Con il vincolo aggiuntivo di avere un numero fisso di livelli gerarchici , puoi farlo con un JOIN multiplo.
Nel caso generale, ci sono diverse modifiche alla struttura per consentire il superamento di tali vincoli. In pratica allenti il vincolo "THIS is my table structure", permettendo l'aggiunta di campi aggiuntivi.
Ad esempio, puoi integrare la struttura del nodo con un left_id
valore e assicurati che tutti gli ID dei nodi siano in sequenza quando visiti l'albero in profondità:
1 --- 2 -+- 3 -+- 4
| |
| +- 5
+- 6 --- 7
In questo caso, il nodo 3 memorizzerebbe il valore "5", il nodo 6 memorizzerebbe il valore "7" e anche il nodo 2 memorizzerebbe il valore "7". Ogni nodo memorizza in LeftID il massimo tra i LeftID dei suoi figli e il proprio ID .
Quindi i nodi senza figli hanno LeftID uguale ai loro ID. Il nodo 1 avrà LeftID 7 poiché è il LeftID di 2, che lo ha ottenuto da 6.
In questa situazione, contando nodi è facile se non ci sono buchi nella sequenza; tutti i discendenti di un nodo sono quei nodi il cui ID è compreso tra l'ID del nodo iniziale e il suo LeftID; e le foglie sono identificate avendo LeftID uguale a ID.
Quindi "tutte le foglie che discendono dall'id del nodo 17" sarebbero
SELECT child.*FROM tabella AS parentJOIN table AS childON (child.id> parent.id AND child.id <=parent.leftid ) /* Discendente /WHERE child.id =child.leftid / Foglia /AND parent.id =17; / Il genitore ha 17 anni
Questa struttura è scomoda da mantenere se vuoi essere in grado di eseguire potature e ramificazioni, poiché devi rinumerare tutti i nodi tra il punto di potatura fino al punto di diramazione, così come i nodi spostati.
Un'altra possibilità se sei interessato solo al conteggio è tenere un contatore figlio. Questo può essere mantenuto aggiornandolo in modo iterativo, selezionando tutte le foglie e impostando il loro contatore a 0 (identifichi le foglie tramite un LEFT JOIN); quindi tutti quei genitori con contatori NULL che hanno figli con contatori non NULL, aggiornando i loro contatori al SUM()
di contatori bambini più il COUNT()
dei bambini stessi; e continuando fino a quando il numero di righe aggiornate diventa zero, poiché tutti i nodi hanno contatori non NULL. Dopo una potatura e rami, imposta tutti i contatori su NULL e ripeti.
Quest'ultimo approccio costa un'unione riflessiva per ogni livello della gerarchia.