Hierarchische Tabelle - wie man Pfade der Elemente [verknüpfte Listen in MySQL] erhält

8

Ich habe eine hierarchische Tabelle in MySQL: parent Feld jedes Elements zeigt auf das Feld id des übergeordneten Elements. Für jedes Element kann ich die Liste aller Eltern [unabhängig von der Tiefe] mit dem Abfrage beschrieben . Mit GROUP_CONCAT erhalte ich den vollständigen Pfad als eine einzelne Zeichenfolge:

%Vor%

Ich kann das nur machen, wenn der id des Items fest ist [in diesem Fall 200 ].

Ich möchte das Gleiche für alle Zeilen tun: Abfrage der gesamten Tabelle mit einem zusätzlichen Feld ( path ), das den vollständigen Pfad anzeigt. Die einzige Lösung, die mir in den Sinn kommt, besteht darin, diese Abfrage in eine andere Auswahl einzubetten, eine temporäre Variable @id festzulegen und sie in der Unterabfrage zu verwenden. Aber es funktioniert nicht. Ich bekomme NULL s im Feld path .

%Vor%

PS Ich weiß, dass ich die Pfade in einem separaten Feld speichern und sie beim Einfügen / Aktualisieren aktualisieren kann, aber ich brauche eine Lösung basierend auf der verknüpften Listentechnik .

UPDATE: Ich würde gerne eine Lösung sehen, die keine Rekursion oder Konstrukte wie for und while verwendet. Das obige Verfahren zum Finden von Pfaden verwendet keine Schleifen oder Funktionen. Ich möchte in derselben Logik eine Lösung finden. Oder, wenn es unmöglich ist, bitte versuchen Sie, warum zu erklären!

    
Hrant Khachatrian 20.08.2012, 08:47
quelle

2 Antworten

2

Berücksichtigen Sie den Unterschied zwischen den folgenden zwei Abfragen:

%Vor%

Sie sehen fast identisch aus, ergeben aber dramatisch unterschiedliche Ergebnisse. In meiner Version von MySQL ist _id in der zweiten Abfrage für jede Zeile in der Ergebnismenge identisch und entspricht der id der letzten Zeile. Dieses letzte Bit ist jedoch nur wahr, weil ich die zwei Abfragen in der angegebenen Reihenfolge ausgeführt habe. Nach SET @id := 1 zum Beispiel kann ich sehen, dass _id immer gleich dem Wert in der SET -Anweisung ist.

Also, was ist hier los? Ein EXPLAIN liefert einen Hinweis:

%Vor%

Diese dritte Zeile, die Tabelle DERIVED ohne verwendete Tabellen, gibt MySQL an, dass es jederzeit genau einmal berechnet werden kann. Der Server bemerkt nicht, dass die abgeleitete Tabelle eine Variable verwendet, die anderswo in der Abfrage definiert ist, und hat keine Ahnung, dass sie einmal pro Zeile ausgeführt werden soll. Sie werden von einem Verhalten gebissen, das in der MySQL-Dokumentation zu benutzerdefinierten Variablen :

  

Als allgemeine Regel sollten Sie niemals einer Benutzervariablen einen Wert zuweisen   und lies den Wert in derselben Anweisung. Du könntest das bekommen   Ergebnisse erwarten Sie, aber das ist nicht garantiert. Die Reihenfolge von   Auswertung für Ausdrücke mit Benutzervariablen ist undefiniert und   kann sich basierend auf den Elementen ändern, die in einer gegebenen Aussage enthalten sind;   Außerdem ist diese Reihenfolge nicht garantiert   Versionen des MySQL-Servers.

In meinem Fall wird zuerst die Tabelle berechnet, bevor @id durch das äußere SELECT (neu) definiert wird. Genau aus diesem Grund funktioniert die ursprüngliche hierarchische Datenabfrage. Die @r -Definition wird von MySQL vor allem anderen in der Abfrage berechnet, genau weil es diese Art von abgeleiteter Tabelle ist. Allerdings müssen wir hier @r einmal pro Tabellenzeile zurücksetzen, nicht nur einmal für die gesamte Abfrage. Um dies zu tun, benötigen wir eine Abfrage, die wie die ursprüngliche aussieht und @r von Hand zurücksetzt.

%Vor%

Diese Abfrage verwendet das zweite t_hierarchy genauso wie die ursprüngliche Abfrage, um sicherzustellen, dass im Ergebnis genügend Zeilen vorhanden sind, damit die übergeordnete Unterabfrage durchlaufen werden kann. Es fügt auch eine Zeile für jede _id hinzu, die sich selbst als Eltern enthält. Andernfalls würden alle Stammobjekte (mit NULL im übergeordneten Feld) überhaupt nicht in den Ergebnissen angezeigt.

Seltsamerweise scheint das Ausführen des Ergebnisses über GROUP_CONCAT die Reihenfolge zu stören. Glücklicherweise hat diese Funktion ihre eigene ORDER BY -Klausel:

%Vor%

Faire Warnung: Diese Abfragen basieren implizit auf den Aktualisierungen @r und @l , die vor der Aktualisierung @c stattfinden. Diese Reihenfolge wird von MySQL nicht garantiert und kann sich mit jeder Version des Servers ändern.

    
eswald 29.08.2012 18:36
quelle
1

Definieren Sie die Funktion "getPath" und führen Sie die folgende Abfrage aus:

%Vor%

Definieren der Funktion "getPath":

%Vor%     
Amy A 29.08.2012 05:10
quelle