Biorąc pod uwagę te ograniczenia, nie ma mowy. W takim przypadku albo odzyskasz wszystkie drzewo i zbuduj stronę klienta „wzgórza” lub wykonaj zapytania rekurencyjne, cokolwiek byłoby najbardziej wydajne w konkretnym przypadku.
Z dodatkowym ograniczeniem mania stałej liczby poziomów hierarchii , możesz to zrobić za pomocą wielokrotnego POŁĄCZENIA.
W ogólnym przypadku istnieje kilka modyfikacji konstrukcji, które umożliwiają pokonanie tych ograniczeń. W praktyce łagodzisz ograniczenie „TO JEST moja struktura tabeli”, pozwalając na dodanie dodatkowych pól.
Na przykład możesz uzupełnić strukturę węzłów o left_id
i upewnij się, że wszystkie identyfikatory węzłów są w kolejności, gdy odwiedzasz drzewo w pierwszej kolejności:
1 --- 2 -+- 3 -+- 4
| |
| +- 5
+- 6 --- 7
W tym przypadku węzeł 3 przechowuje wartość „5”, węzeł 6 przechowuje wartość „7”, a węzeł 2 również przechowuje wartość „7”. Każdy węzeł przechowuje w LeftID maksimum między identyfikatorami LeftID swoich dzieci a własnym identyfikatorem .
Tak więc węzły bezdzietne mają LeftID równe ich identyfikatorom. Węzeł 1 będzie miał LeftID 7, ponieważ jest to LeftID 2, które otrzymało go z 6.
W tej sytuacji liczenie węzły jest łatwe, jeśli w sekwencji nie ma dziur; wszyscy potomkowie węzła to te węzły, których ID znajduje się pomiędzy ID węzła początkowego a jego LeftID; a liście są identyfikowane przez LeftID równe ID.
Tak więc „wszystkie liście opadające od węzła o identyfikatorze 17” byłyby
SELECT dziecko.*FROM tabela AS parentJOIN tabela AS childON (child.id> parent.id AND child.id <=parent.leftid ) /* Potomek /WHERE child.id =child.leftid / Liść /ORAZ parent.id =17; / Rodzic ma 17 lat
Ta struktura jest niewygodna w utrzymaniu, jeśli chcesz mieć możliwość wykonywania operacji prune i branch, ponieważ musisz przenumerować wszystkie węzły między punktem prune a punktem branch, a także przeniesione węzły.
Inną możliwością, jeśli interesuje Cię tylko liczenie, jest prowadzenie licznika dzieci. Można to utrzymać, aktualizując go iteracyjnie, wybierając wszystkie liście i ustawiając ich licznik na 0 (liście identyfikuje się poprzez LEFT JOIN); następnie wszyscy rodzice z licznikami NULL, którzy mają dzieci z licznikami innymi niż NULL, aktualizując ich liczniki do SUM()
liczników dzieci plus COUNT()
samych dzieci; i kontynuuj, aż liczba zaktualizowanych wierszy osiągnie zero, ponieważ wszystkie węzły mają liczniki inne niż NULL. Po przycinaniu i rozgałęzianiu po prostu ustawiasz wszystkie liczniki na NULL i powtarzasz.
To ostatnie podejście kosztuje refleksyjne połączenie dla każdego poziomu hierarchii.