Mysql
 sql >> Database >  >> RDS >> Mysql

Interrogazione di un conteggio di elementi di un albero

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.