Il existe d'autres façons d'organiser les données hiérarchiques en plus des méthodes présentées dans le blog de Mike Hillyer. J'aime utiliser une méthode que j'appelle table de fermeture transitive ou table de fermeture pour faire court. Dans cette conception, vous stockez chaque chemin dans la hiérarchie, sous forme de paires ancêtre/descendant.
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);
Notez que cet ensemble inclut même les "chemins" de longueur zéro, c'est-à-dire qu'un élément de menu est un "parent" de lui-même.
Vous pouvez maintenant rejoindre chaque élément de menu m
à chaque ensemble d'ancêtres a
, en se joignant aux chemins où m
est le descendant. De là, revenez à l'élément de menu o
qui se trouve dans l'ensemble des ancêtres, et vous pouvez accéder à l'order
.
Utilisez GROUP_CONCAT() pour créer une chaîne de "fil d'Ariane" à partir de la order
de chacun dans la chaîne d'ancêtres, et cela devient une chaîne que vous pouvez trier pour obtenir l'ordre de menu que vous souhaitez.
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 |
+----+----------+-------+-------------+
Notez que le fil d'Ariane est trié comme une chaîne, donc si vous avez un certain order
nombres à 2 ou 3 chiffres, vous obtiendrez des résultats irréguliers. Assurez-vous que votre order
les nombres ont tous le même nombre de chiffres.
Comme alternative, vous pouvez simplement stocker les chaînes de fil d'Ariane dans votre tableau de menu d'origine :
ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.
Ensuite, vous pouvez faire une requête plus simple :
SELECT * FROM menu ORDER BY breadcrumbs;
Mais ensuite, c'est à vous de recalculer manuellement toutes les chaînes de fil d'Ariane concernées, si jamais vous modifiez l'ordre des éléments de menu.