Compte tenu de ces contraintes, il n'y a aucun moyen. Dans ce cas, vous récupérez tous l'arborescence et construire un côté client "colline", ou effectuer des requêtes récursives, ce qui serait le plus performant dans le cas spécifique.
Avec la contrainte supplémentaire d'avoir un nombre fixe de niveaux hiérarchiques , vous pouvez le faire avec un multiple JOIN.
Dans le cas général, il existe plusieurs modifications de structure pour permettre de s'affranchir de ces contraintes. En pratique, vous relâchez la contrainte "CECI est ma structure de table", permettant l'ajout de champs supplémentaires.
Par exemple, vous pouvez compléter la structure du nœud avec un left_id
et assurez-vous que tous les ID de nœud sont dans l'ordre lorsque vous visitez l'arborescence en premier :
1 --- 2 -+- 3 -+- 4
| |
| +- 5
+- 6 --- 7
Dans ce cas, le nœud 3 stockerait la valeur "5", le nœud 6 stockerait la valeur "7", et le nœud 2 stockerait également la valeur "7". Chaque nœud stocke dans LeftID le maximum entre les LeftID de ses enfants et son propre ID .
Ainsi, les nœuds sans enfants ont LeftID égal à leurs ID. Le nœud 1 aura LeftID 7 puisque c'est le LeftID de 2, qui l'a obtenu de 6.
Dans cette situation, compter nœuds est facile s'il n'y a pas de trous dans la séquence ; tous les descendants d'un nœud sont les nœuds dont l'ID est compris entre l'ID du nœud de départ et son LeftID ; et les feuilles sont identifiées en ayant LeftID égal à ID.
Ainsi, "toutes les feuilles descendant de l'ID de nœud 17" seraient
SELECT child.*FROM table AS parentJOIN table AS childON (child.id> parent.id AND child.id <=parent.leftid ) /* Descendant /WHERE child.id =child.leftid / Feuille /AND parent.id =17 ; / Le parent a 17 ans
Cette structure est difficile à maintenir si vous voulez pouvoir faire des élagages et des branchements, car vous devez renuméroter tous les nœuds entre le point d'élagage et le point de branchement, ainsi que les nœuds déplacés.
Une autre possibilité si vous êtes seulement intéressé par le comptage est de garder un compteur enfant. Cela peut être maintenu en le mettant à jour de manière itérative, en sélectionnant toutes les feuilles et en mettant leur compteur à 0 (vous identifiez les feuilles via un LEFT JOIN); puis tous ces parents avec des compteurs NULL qui ont des enfants avec des compteurs non NULL, mettant à jour leurs compteurs avec SUM()
des compteurs des enfants plus le COUNT()
des enfants eux-mêmes; et continuer jusqu'à ce que le nombre de lignes mises à jour devienne zéro, car tous les nœuds ont des compteurs non NULL. Après un élagage et une branche, il vous suffit de définir tous les compteurs sur NULL et de répéter.
Cette dernière approche coûte une jointure réflexive pour chaque niveau de hiérarchie.