Erste konsistenter Menübaum Daten aus dem Menü Tabellen in MySQL
-
13-09-2019 - |
Frage
Ich habe ein Baum / Vorfahre / query Problem, das ich nicht in der Lage bin zu lösen:
Ich habe eine Tabelle halten Menüdaten und eine Tabelle, die alle Vorfahren des Menüs enthalten:
table menu table ancestors
+-----+------------+--------+ +---------+--------------+-------+
| id | title | active | | menu_id | ancestor_id | level |
+-----+------------+--------+ +---------+--------------+-------+
| 1 | Home | 0 | | 1 | 0 | 0 |
| 2 | News | 0 | | 2 | 1 | 1 |
| 3 | Foo | 0 | | 3 | 2 | 2 |
| 4 | Bar | 1 | | 3 | 1 | 1 |
| 5 | Downloads | 1 | | 4 | 3 | 3 |
+-----+------------+--------+ | 4 | 2 | 2 |
| 4 | 1 | 1 |
| 5 | 1 | 1 |
+---------+--------------+-------+
Ich bekomme alle aktiven Menüeinträge mit ihren Vorfahren leicht mit:
SELECT menu.id, menu.title, GROUP_CONCAT(ancestors.ancestor_id) as ancestors
FROM menu, ancestors
WHERE menu.active = 1
GROUP BY (menu.id);
+----+-----------+----------+
| id | title |ancestors |
+----+-----------+----------+
| 4 | Bar | 3,2,1 |
| 5 | Downloads | 1 |
+----+-----------+----------+
Aber wie kann ich alle die für den Baum notwendig Vorfahren erhalten, auch? In meinem Ergebnis würde ich den Eintrag Foo und Nachrichten braucht, so dass ich die gleich bleibenden Baum zu bekommen. Es soll wie folgt aussehen:
+----+-----------+----------+
| id | title |ancestors |
+----+-----------+----------+
| 2 | News | 1 |
| 3 | Foo | 2,1 |
| 4 | Bar | 3,2,1 |
| 5 | Downloads | 1 |
+----+-----------+----------+
Wie hat sich die Abfrage wie zu sein?
Lösung
Wenn ich das tue, ich die ancestors
Tabelle etwas anders strukturieren. Statt level
, speichere ich pathlength
. Auch speichern Sie eine Zeile für jeden Menüpunkt zu sich selbst zu zeigen, mit einer Weglänge von 0.
+---------+--------------+------------+
| menu_id | ancestor_id | pathlength |
+---------+--------------+------------+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 0 |
| 2 | 1 | 1 |
| 3 | 2 | 2 |
| 3 | 1 | 1 |
| 4 | 3 | 3 |
| 4 | 2 | 2 |
| 4 | 1 | 1 |
| 5 | 1 | 1 |
+---------+--------------+------------+
Diese „reflexive“ Einträge können Sie den Satz von aktiven Menüpunkte zur Schließung Tisch verbinden. Ändern Ebene Weglängen ermöglicht es Ihnen, die reflexiven Einträge aus der Menge der Vorfahren auszuschließen.
Jetzt können Sie alle Menüpunkte abfragen, die Vorfahren der „aktiven“ Menüpunkte, einschließlich der aktiven Menüpunkte selbst:
SELECT a2.menu_id, m2.title, GROUP_CONCAT(a2.ancestor_id) AS ancestors
FROM menu m1
JOIN ancestors a1 ON (m1.id = a1.menu_id)
JOIN ancestors a2 ON (a1.ancestor_id = a2.menu_id AND a2.pathlength > 0)
JOIN menu m2 ON (a2.menu_id = m2.id)
WHERE m1.active = 1
GROUP BY a2.menu_id;
Ergebnis:
+---------+-----------+-----------+
| menu_id | title | ancestors |
+---------+-----------+-----------+
| 2 | News | 1 |
| 3 | Foo | 2,1 |
| 4 | Bar | 3,2,1 |
| 5 | Downloads | 1 |
+---------+-----------+-----------+