Има и други начини за организиране на йерархични данни освен методите, показани в блога на Майк Хилър. Обичам да използвам метод, който наричам преходна таблица за затваряне или накратко таблица за затваряне. В този дизайн вие съхранявате всеки път през йерархията като двойки предшественик/наследник.
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);
Имайте предвид, че този набор включва дори „пътеките“ с нулева дължина, т.е. елемент от менюто е „родител“ сам за себе си.
Сега можете да се присъедините към всеки елемент от менюто m
на всеки негов набор от предци a
, чрез присъединяване към пътища, където m
е дескандантът. Оттам се присъединете обратно към елемента от менюто o
който е в набора от предшественици и можете да получите достъп до order
.
Използвайте GROUP_CONCAT(), за да направите низ от "хлебни трохи" от order
от всеки във веригата от предци и това се превръща в низ, по който можете да сортирате, за да получите желания ред на менюто.
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 |
+----+----------+-------+-------------+
Имайте предвид, че галетата се сортират като низ, така че ако имате някакъв order
числа с 2 или 3 цифри, ще получите неправилни резултати. Уверете се, че вашата order
всички числа имат еднакъв брой цифри.
Като алтернатива можете просто да съхраните низовете на галета в оригиналната си таблица на менюто:
ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.
След това можете да направите по-проста заявка:
SELECT * FROM menu ORDER BY breadcrumbs;
Но след това зависи от вас да преизчислите ръчно всички засегнати низове на галерията, ако някога промените реда на елементите от менюто.