Poza metodami przedstawionymi na blogu Mike'a Hillyera istnieją inne sposoby organizowania danych hierarchicznych. Lubię używać metody, którą nazywam tablicą przechodniego zamknięcia lub stół zamykający w skrócie. W tym projekcie przechowujesz każdą ścieżkę w hierarchii jako pary przodek/potomek.
create table closure (
ancestor int,
descendant int,
length int,
primary key (ancestor,descendant),
key (descendant,ancestor)
);
insert into closure values
(1,1,0),
(1,3,1),
(1,4,2),
(1,5,3),
(2,2,0),
(3,3,0),
(3,4,1),
(3,5,2),
(4,4,0),
(4,5,1),
(5,5,0);
Zwróć uwagę, że ten zestaw zawiera nawet „ścieżki” o długości zerowej, tj. element menu jest „rodzicem” samego siebie.
Teraz możesz dołączyć do każdego elementu menu m
do każdego jego zestawu przodków a
, łącząc się ze ścieżkami, w których m
jest dekanantem. Stamtąd dołącz z powrotem do pozycji menu o
który znajduje się w zestawie przodków i możesz uzyskać dostęp do order
.
Użyj GROUP_CONCAT(), aby utworzyć ciąg „bułka tarta” z order
każdego z nich w łańcuchu przodków, a to staje się łańcuchem, według którego możesz sortować, aby uzyskać żądaną kolejność menu.
SELECT m.*, GROUP_CONCAT(o.`order` ORDER BY a.length DESC) AS breadcrumbs
FROM menu AS m
INNER JOIN closure AS a ON a.descendant = m.id
INNER JOIN menu AS o ON a.ancestor = o.id
GROUP BY m.id
ORDER BY breadcrumbs;
+----+----------+-------+-------------+
| id | name | order | breadcrumbs |
+----+----------+-------+-------------+
| 1 | Father1 | 0 | 0 |
| 3 | Son | 0 | 0,0 |
| 4 | Child | 1 | 0,0,1 |
| 5 | Grandson | 2 | 0,0,1,2 |
| 2 | Father2 | 1 | 1 |
+----+----------+-------+-------------+
Zwróć uwagę, że bułka tarta sortuje się jako ciąg, więc jeśli masz jakieś order
numery z 2 lub 3 cyframi, otrzymasz nieregularne wyniki. Upewnij się, że Twoje order
wszystkie liczby mają taką samą liczbę cyfr.
Jako alternatywę możesz po prostu przechowywać ciągi bułki tartej w oryginalnej tabeli menu:
ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.
Następnie możesz wykonać prostsze zapytanie:
SELECT * FROM menu ORDER BY breadcrumbs;
Ale wtedy to do Ciebie należy ręczne ponowne obliczenie wszystkich dotkniętych ciągów bułki tartej, jeśli kiedykolwiek zmienisz kolejność elementów menu.