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?

War es hilfreich?

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         | 
+---------+-----------+-----------+
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top