Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Baum geordnet nach Eltern und Kind

Neben den in Mike Hillyers Blog gezeigten Methoden gibt es noch andere Möglichkeiten, hierarchische Daten zu organisieren. Ich verwende gerne eine Methode, die ich transitive Closure Table nenne oder Verschlusstisch kurz. In diesem Design speichern Sie jeden Pfad durch die Hierarchie als Vorfahren/Nachkommen-Paare.

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);

Beachten Sie, dass dieser Satz sogar die "Pfade" der Länge Null enthält, d. h. ein Menüpunkt ist ein "Elternteil" von sich selbst.

Nun können Sie jedem Menüpunkt m beitreten zu jedem seiner Vorfahren a , indem Sie Pfaden beitreten, in denen m ist der Nachkomme. Gehen Sie von dort zurück zum Menüpunkt o die sich in der Gruppe der Vorfahren befindet, und Sie können auf die order zugreifen .

Verwenden Sie GROUP_CONCAT(), um aus der order eine Zeichenfolge aus "Breadcrumbs" zu erstellen von jedem in der Kette der Vorfahren, und dies wird zu einer Zeichenfolge, nach der Sie sortieren können, um die gewünschte Menüreihenfolge zu erhalten.

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           |
+----+----------+-------+-------------+

Beachten Sie, dass die Breadcrumbs als String sortiert werden, wenn Sie also eine order haben Zahlen mit 2 oder 3 Ziffern erhalten Sie unregelmäßige Ergebnisse. Stellen Sie Ihre order sicher Nummern haben alle die gleiche Anzahl an Stellen.

Alternativ könnten Sie die Breadcrumbs-Strings einfach in Ihrer ursprünglichen Menütabelle speichern:

ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.

Dann können Sie eine einfachere Abfrage durchführen:

SELECT * FROM menu ORDER BY breadcrumbs;

Aber dann liegt es an Ihnen, alle betroffenen Breadcrumb-Strings manuell neu zu berechnen, wenn Sie jemals die Reihenfolge der Menüpunkte ändern.