Nested Sets – Hierarchische Strukturen und Bäume in MySQL

Wir haben bereits gesehen, dass das rekursive Abfragen eines Baumes, der über Parent-IDs verwirklicht wurde, sehr langsam ist. Dieses Problem soll nun umgangen werden, damit wir mit nur einer SELECT-Abfrage und ohne jegliche Rekursion (auch kein connect by prior, wie es in Oracle möglich ist) alle Datensätze und die dazugehörigen Ebenen erhalten.

Das Modell der Nested Sets stammt von Joe Celko. Mittlerweile sind zum ursprünglichen Verfahren noch ein paar Kniffe hinzugekommen, die Grundidee aber ist gleich geblieben – und aus Performance-Sicht ein wahrer Segen.

Das Konzept
Arne Klempert beschreibt das Verfahren meiner Meinung nach am verständlichsten, deshalb möchte ich dieses Beitrag auf seine Ausführungen stützen.
Das Konzept von Nested Sets basiert auf Mengen. Wir stellen uns allerdings weniger das Mengenmodell vor sondern vielmehr einen Zahlenstrahl (zum besseren Nachvollziehen genügt auch ein Lineal). Zahlenstrahl-Modell der Nested SetsDen Kategorien wurde ein bestimmter Bereich auf diesem Zahlenstrahl zugewiesen. Im Bild ist die Beziehung von Säugetierklasen dargestellt. Die oberste Kategorie Säugetiere hat einen Bereich von 1 bis 10. Innerhalb dieses Bereichs sind alle Kind-Kategorien von Säugetiere – so z.B. Primaten (Bereich 2 bis 7). Und Unterkategorien der Primaten sind wiederum im Bereich zwischen 2 und 7, z.B. Halbaffen (3 – 4) und Affen (5 – 6).
Hieran wird das Konzept deutlich: Alle Kategorien, die unter einer übergeordneten Kategorie H liegen, haben einen Zahlenbereich innerhalb des zu H zugewiesenen Bereiches.

In der Datenbank wird das über 2 zusätzliche Spalten umgesetzt, die wir der Kategorie-Tabelle hinzufügen: lft (die linke Grenze des Bereiches einer Kategorie) und rgt (die rechte Grenze).
Wie baut man das ganze nun auf?

Der Aufbau
Als Beispiel wollen wir wieder die Online-Shop-Kategorien wählen. Hier nochmal die Struktur:

  • Lebensmittel
    • Getränke
    • Gemüse
      • Broccoli
      • Kohlrabi
    • Obst
      • Pfirsich
      • Orange
  • Kleidung
    • Herrenkleidung
    • Damenkleidung

Unsere Kategorien-Tabelle sieht so aus:

CREATE TABLE kategorien (
    ID    INT(12)      UNSIGNED NOT NULL AUTO_INCREMENT,
    name  VARCHAR(50)  NOT NULL,
    lft   INT(12)      UNSIGNED NOT NULL,
    rgt   INT(12)      UNSIGNED NOT NULL,
    PRIMARY KEY (id),
    KEY lft (lft),
    KEY rgt (rgt)
);

Wenn wir die erste Kategorie hinzufügen wollen, tun wir dies mittels

INSERT INTO kategorien (name,lft,rgt) VALUES  ('Lebensmittel',1,2);

Wieso lft=1 und rgt=2? Wenn die erste Kategorie eingefügt wird, bekommt diese Kategorie einfach den Bereich 1 und 2 – ohne Begründung 🙂
Nun wollen wir Gemüse unter die Lebensmittel hängen. Dazu muss natürlich der Bereich der Lebensmittel erweitern werden, damit der Grundsatz wieder passt, dass alle Unterkategorien innerhalb des Bereiches der Oberkategorie liegen.

UPDATE kategorien SET rgt=rgt+2 WHERE rgt >= 2;
INSERT INTO kategorien (name,lft,rgt) VALUES ('Gemüse',2,3);

Das Update schafft den nötigen Platz (neuer Bereich von Lebensmittel ist 1-4). Das Insert hat als lft-Wert den alten rgt-Wert der übergeordneten Kategorie (nämlich 2) und als rgt-Wert bekommt die neue Kategorie den alten rgt-Wert der übergeordneten Kategorie + 1.
Wenn wir nun den Bruder Obst einfügen, führen wir die gleiche Query wie oben wieder aus, wobei der alte rgt-Wert der übergeordneten Kategorie (Lebensmittel) als Variable $RGT (in diesem Beispiel 4) angenommen wird (wenn nicht bekannt, einfach per SELECT-Statement vorher abfragen und speichern).

UPDATE kategorien SET rgt=rgt+2 WHERE rgt >= $RGT;
INSERT INTO kategorien (name,lft,rgt) VALUES ('Obst',$RGT,$RGT+1);

Wir haben nun also folgende Tabelle:

ID name lft rgt
1 Lebensmittel 1 6
2 Gemüse 2 3
3 Obst 4 5

Wenn wir nun aber nicht immer sofort alle Kind-Kategorien hinzufügen, sondern merken, dass wir zwischendurch eine vergessen haben, müssen auch die lft-Werte upgedatet werden. Beispielsweise wollen wir nun Broccoli hinzufügen. $RGT ist also 3, da die übergeordnete Kategorie Gemüse zu diesem Zeitpunkt diesen rgt-Wert hat.

UPDATE kategorien SET rgt=rgt+2 WHERE rgt >= $RGT;
UPDATE kategorien SET lft=lft+2 WHERE lft > $RGT;
INSERT INTO kategorien (name,lft,rgt) VALUES ('Broccoli',$RGT,$RGT+1);

Dieses Statement ist dann auch das entscheidende beim Eintragen. Die vorhergehenden sollten nur mit geringerer Komplexität das Konzept verdeutlichen. Die gleichen Ergebnisse wären aber entstanden, wenn wir diese 3 Queries angewendet hätten.

Um etwas Performance noch herauszuholen, könnte man die beiden Updates noch etwas entschärfen, da bei den Datensätzen, wo der lft-Wert > $RGT gilt, dass auch der rgt-Wert &gt $RGT (da rgt immer größer als lft ist):

UPDATE kategorien SET rgt=rgt+2, lft=lft+2 WHERE lft > $RGT;
UPDATE kategorien SET rgt=rgt+2 WHERE rgt = $RGT;

Dadurch haben wir immernoch 2 Updates, aber es müssen weniger Einzel-Updates durchgeführt werden. Bei der oben genannten Variante sind es fürs erste Update N – $RGT +1 Datensätze und fürs zweite N – $RGT = (N-$RGT+1) + (N – $RGT) = 2*N – 2*$RGT +1.
Die schnellere Variante braucht nur N – $RGT Datensätze fürs erste Update und 1 fürs 2. Update aktualisieren. Das sind N – $RGT + 1. Und es gilt N – $RGT + 1 < 2*N - 2*$RGT + 1. Man braucht also N - $RGT Einzelupdates weniger. Wenn wir eine neue Hauptkategorie hinzufügen möchten, müssen wir den aktuell größten rgt-Wert der Tabelle ermitteln und diesen um 1 erhöhen, um den lft-Wert bzw. um 2 erhöhen um den rgt-Wert der neuen Hauptkategorie (keine übergeordnete Kategorie) zu ermitteln.

ID name lft rgt
1 Lebensmittel 1 16
2 Gemüse 2 7
3 Obst 8 13
4 Broccoli 3 4
5 Kleidung 17 22
6 Kohlrabi 5 6
7 Pfirsich 9 10
8 Herrenkleidung 18 19
9 Damenbekleidung 20 21
10 Orange 11 12
11 Getränke 14 15

Was ist nun gewonnen?
Es ist recht aufwändig die Nested-Set-Struktur zu erstellen, aber sie ist unschlagbar beim Auslesen. Deshalb wird dieses Modell auch eher für Anwendungen empfohlen, die recht selten geändert werden aber umso öfter gelesen werden. Was „recht selten“ bedeutet, muss jeder selbst entscheiden, denn es ist ein Unterschied, ob die Kategorien einmal im Monat verändert werden oder ob stündlich eine Veränderung in der Struktur geschieht. Im Grunde ist sie aber für fast alle Anwendungsgebiete im Web, die eine Hierarchie in einer Datenbank ablegen geeignet.

Für das Auslesen des kompletten Baums inklusive der Ebenen ist nur noch eine Abfrage nötig:

SELECT n.name, COUNT(*)-1 AS ebene
FROM kategorien AS n,kategorien AS p
WHERE n.lft BETWEEN p.lft AND p.rgt
GROUP BY n.lft
ORDER BY n.lft;

Dadurch erhält man das gewünschte Ergebnis, dass zwischen 2 Kategorien der gleichen Ebene ersmtal alle Kind-Kategorien kommen. Somit kann man das Ergebnis wunderbar zu der visualisierten Baumstruktur verwenden.

Zusätzlich lassen sich aus dem Baum noch mehr Informationen ermitteln:

SELECT n.*,
round((n.rgt-n.lft-1)/2,0) AS countUntergeordnete,
COUNT(*)-1+(n.lft>1) AS ebene,
((MIN(p.rgt)-n.rgt-(n.lft>1))/2) > 0 AS countVorgaengerGleicheEbene,
(((n.lft-MAX(p.lft)>1))) AS countNachfolgerGleicheEbene
FROM kategorien n, kategorien p
WHERE n.lft BETWEEN p.lft AND p.rgt AND (p.id != n.id OR n.lft = 1)
GROUP BY n.id
ORDER BY n.lft;

Solch komplexe Abfragen sind allerdings eher selten nötig, aber möglich.

Wir wollen uns lieber mit für die Praxis wichtigeren Abfragen beschäftigen:
Zum Beispiel für Breadcrumbs ist es noch wichtig alle übergeordneten Kategorien zu ermitteln von einer Unterkategorie ausgehend. Wir möchten beispielsweise den kompletten Baum über der Kategorie Pfirsich (ID: 7) ermitteln.

SELECT p.*
FROM kategorien n, kategorien p
WHERE n.lft BETWEEN p.lft AND p.rgt
AND n.id = 7
ORDER BY n.lft;

Als Ergebnis erhält man Lebensmittel > Obst > Pfirsich (als 3 Datensätze) in der gewünschten Reihenfolge von der Wurzel bis zur Kategorie Pfirsich.

Entfernen von Kategorien
Wichtig ist in der Praxis noch, wie man Kategorien wieder entfernen kann.
Sollen alle Kategorien unter einer bestimmten (bzw. nur diese eine, wenn sie keine Kinder hat) gelöscht werden, sind diese Befehle nützlich ($LFT und $RGT sind die lft- und rgt-Werte der zu löschenden Kategorie):

DELETE FROM kategorien WHERE lft BETWEEN $LFT AND $RGT;
UPDATE kategorien SET lft=lft-$RGT-$LFT+1 WHERE lft>$RGT;
UPDATE kategorien SET rgt=rgt-$RGT-$LFT+1 WHERE rgt>$RGT;

Arne Klempert beschreibt es zwar mit einer zusätzlichen ROUND-Funktion, allerdings ist mir nicht klar weshalb, denn bei Addition und Subtraktion mit natürlichen Zahlen kommt stets eine natürliche Zahl heraus.
Wenn darunterliegende Kategorien nicht mit gelöscht werden sollen, sondern eine Ebene nach oben geschoben, ist folgende Query die richtige:

DELETE FROM kategorien WHERE lft BETWEEN $LFT AND $RGT;
UPDATE kategorien SET lft=lft-1, rgt=rgt-1 WHERE lft BETWEEN $LFT AND $RGT;
UPDATE kategorien SET lft=lft-2 WHERE lft>$RGT;
UPDATE kategorien SET rgt=rgt-2 WHERE rgt>$RGT;

Ich hoffe ich konnte das Konzept von Nested Sets etwas näherbringen, denn ich habe die Erfahrung gemacht, dass selbst langjährige Datenbank-Administratoren von diesem Modell nichts wussten und ganz erstaunt waren. Ich empfehle auf jeden Fall die Lektüre Nested Sets – Verschachtelte Bäume mit MySQL.

Jan hat 152 Beiträge geschrieben

66 Kommentare zu “Nested Sets – Hierarchische Strukturen und Bäume in MySQL

  1. Artemis sagt:

    Ich hatte mich vorher schon einmal mit Nested Sets befasst, das ganze aber nicht wirklich verstanden. Dieser Artikel, und vor allem das Bild vom Anfang, haben mir das ganze aber klar gemacht.

    Danke dafür,
    Artemis

  2. Scar sagt:

    ich bastel grad an einem kleinen cms Projekt zum Spaß (und lernen) rum und wollte eigentlich im Netz rausfinden wie man ordentliche Bäume via Rekursion baut (hab eszwar hinbekommen, wollte aber mal schaun, was ich verbessern kann – ich hasse Rekursion), da bin ich hier rauf gestoßen. Tolles Konzept und tolle Erklärung von dir, danke. Werd ich in jedem Fall verwenden.

    Mfg

  3. ex sagt:

    Hi,

    wirklich sehr toll erklärt! Hatte die Tage aus Langeweile mal an sowas gedacht. Hab erst PEAR Tree ausprobiert, das funktioniert aber anscheinend mit der neusten Version von MDB2 nicht mehr. Dann hab ich die DB_NestedSet Klasse ausprobiert und die ging auch nicht (wurde auch schon sehr lange nicht mehr aktualisert).

    Auf meiner Suche bin ich dann auf diesen Artikel (und das sehr interessante Blog) gestoßen. Hab das Alles in eine NestedSet geschrieben. Funktioniert wirklich toll und wenn man alles Schritt für Schritt durchgeht und das mit den Balken etwas nachskizziert auch ganz verständlich! Super Konzept und Tutorial!

  4. Samas sagt:

    Sehr schöne Erklärung, aber ich fürchte da hat sich ein kleiner Fehler eingeschlichen bei dem finallen Update vor dem Einfügen eines neuen Knotens. Wird nämlich der neue Knoten in die dritte Ebene eingefügt, müssen alle Knoten ‚über‘ diesem neuen Knoten an der rechten Grenze erhöht werden. Das zweite Update

    UPDATE kategorien SET rgt=rgt+2 WHERE rgt = $RGT;

    muß also auf

    UPDATE kategorien SET rgt=rgt+2 WHERE $RGT between lft and rgt;

    geändert werden.

    Schönen Gruß

    Samas

  5. Woody sagt:

    Die oben angegebene SQL-Query zum Erzeugen der Tabelle kategorien ist falsch, hier die berichtigte Version:

    CREATE TABLE kategorien (
    ID INT(12) UNSIGNED NOT NULL AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    lft INT(12) UNSIGNED NOT NULL,
    rgt INT(12) UNSIGNED NOT NULL,
    PRIMARY KEY (id),
    KEY lft (lft),
    KEY rgt (rgt)
    );

  6. Alex sagt:

    Hi. Super Beitrag!

    Ich habe ebenfalls versucht mit Rekursion dieses Problem zu lösen, allerdings nach längeren Überlegungen die Idee verworfen, da inperfomant. Nun bin ich auf den Begriff „Nested Sets“ gestossen und kann mich deinem letzten Satz „…dass selbst langjährige Datenbank-Administratoren von diesem Modell nichts wussten und ganz erstaunt waren“ nur zustimmen.

    An dieser Stelle habe ich noch eine Frage: ist es denn möglich die Ausgabe nach Namen zu sortieren? Also den Baum. Denn die Sortierung wird benötigt um den Baum „richtig“ darstellen zu können. Aber eine Sortierung nach Namen wäre nicht verkehrt.

    Für einen Vorschlag / Idee wäre ich Dankbar.

  7. admin sagt:

    Auf SucheBiete.com nutze ich Nested Sets inkl alphabetischer Sortierung. Der Trick dabei ist, dass man schon bei der Generierung der lft- und rgt-Werte nach dem Alphabet sortiert, sodass beim späteren Selektieren mit dem „ORDER BY lft“ keine Probleme entstehen.

  8. Alex sagt:

    Diesen Gedanken habe ich auch kurz gehabt. Allerdings wird es schwirig bei dynamischer Sortierung. Denn ich versuche einen Verzeichnis samt Dateien abzubilden. Und möchte dem Benutzer es ermöglichen Aufsteigend/Absteigend bzw. ggf. nach der Dateigröße sortieren zu lassen. Oder wenn zuviele Einträge sind, es irgendwie durch Blättern und „anzeigen pro Seite“ darstellen.

    Mir ist ausserdem folgendes aufgefallen und zwar bei der Performancesteigerung. Da steht: (da lft immer größer als rgt ist). Ist das auch so gemeint, oder ein kleiner Dreher?
    Und was noch wichtiger ist: da ist ein Fehler drin (meiner Meinung nach):
    1. UPDATE kategorien SET rgt=rgt+2, lft=lft+2 WHERE lft > $RGT;
    2. UPDATE kategorien SET rgt=rgt+2 WHERE rgt = $RGT;

    Mit dem ersten Statement verschiebst du alle „Mengen“ nach rechts, die komplett (also beiden Grenzen) weiter rechts liegen als $RGT. Mit dem zweiten Statement versuchst du nun die rechte Grenze der Menge um 2 zu verschieben, in die du eine neue Menge einfügen möchtest. Schau dir nun zum Veranschaulichen das bild mit Säugetieren (oben) an. Stell nun mal vor, da ist noch eine Übermenge, die von 1.5 bis 7.5 verläuft. Also die Primaten umfasst (ja, keine Kommazahlen, aber nur zum Verstehen, wo die Grenzen liegen sollen). Die Rechte Grenze dieser Menge wird in diesem Fall nicht angefasst und die Zuordnung gerät durcheinander.

    Gruss,
    Alex

  9. admin sagt:

    Wie gesagt: Für sich häufig ändernde Abfragen bzw Sortierungen sind Nested Sets eher nicht gedacht.

    Und das andere war ein Dreher, hab ich korrigiert. Danke.

  10. Alex sagt:

    Sorry nochmal für diesen Hinweis/Anmerkung (kannst ggf, diese auch Löschen, da nur an dich gerichtet), aber der Vorschlag zur Optimierung ist falsch!
    1. UPDATE kategorien SET rgt=rgt+2, lft=lft+2 WHERE lft > $RGT;
    1. UPDATE kategorien SET rgt=rgt+2 WHERE rgt = $RGT;

    Denn dadurch gehen die Mengen kapput!

  11. LioGetz sagt:

    Sorry, ich komme mir ja schon fast „zu dumm“ vor, aber bin ich der einzige der Probleme damit hat die Daten als „eingerückte Liste (Hauptpunkte – Unterpunkte – Unterunterpunkte)“ in HTML darzustellen?

    Im Beitrag steht: Für das Auslesen des kompletten Baums inklusive der Ebenen ist nur noch eine Abfrage nötig…

    Aber was mache ich dann mit der Abfrage? Es hilft mir nicht weiter wenn ich die Ausgabe dann nach Ebenen sortiert habe…Wie sieht die dazugehörige PHP-Schleife dazu aus…

    Danke im voraus
    CU
    Lio 😀

  12. admin sagt:

    Hallo Lio,

    ich setze diese Art der Struktur ja auch ein. Wenn man das ResultSet einmal hat, dann geht das Auslesen über Rekursion. Du nimmst das erste Element und durchläufst das erste Kind von dem, guckst dann wieder ob dieses Element Kinder hat usw.
    Da Verarbeiten ist deshalb dann wieder etwas aufwändiger als ein klassisches parentOf-Modell, allerdings trotzdem performanter, da die Daten nur von PHP intern rumgeschaufelt werden und nicht ständig MySQL belästigt wird.

  13. JoJo sagt:

    Wie verschiebe ich einen Eintrag ?
    Und wie verschiebe ich einen Knoten mit allen Untereinträgen ?

    Hat jemand einen gültigen funktionierenden SQl Code ?

    Vielen Dank für Eure Hilfe

  14. Jan sagt:

    Ein Verschieben ist nicht möglich. Dazu musst Du den gesamten Baum neu erzeugen. Deshalb ist dieses System auch nur für Anwendungen geeignet, deren Datenbank nur selten geändert wird.

  15. Lisa sagt:

    Irgendwie hänge ich auch an dem Problem aus dem Resultset in HTML eine Ul-LI-Liste zu generieren. Ich komme einfach absolut nicht weiter. Könntest du das vielleicht mal posten wie du das machst? Vielleicht auch gerne in einem extra Blogbeitrag. Die Frage kommt sicherlich öfters vor.

    Finde das wirklich schwierig. 🙁

  16. Lisa sagt:

    Sorry GhostGambler, aber diese Verweise auf Google helfen mir herzlich wenig. Dort gibts 1000 Beiträge mit derselben Frage aber nie Antworten und Lösungen.

  17. Jan sagt:

    Ganz einfach, indem Du beim Ermitteln der lft- und rgt-Werte deine Kategorien (oder was auch immer) nach Namen sortierst. Ich empfehle ja eine zusätzliche Spalte parentID, damit ist das sehr viel einfacher – und man kann die lft- und rgt-Werte immer wieder herstellen.

  18. Jan sagt:

    Nunja, das ganze geht dann wie früher eben rekursiv für das Erstellen des Nes Sets.

    function funktion($curID) {
    SELECT ID FROM kategorien WHERE parent='“.$curID.“‚ ORDER BY name

    while(…) {
    UPDATE kategorien SET lft=…,rgt=… WHERE ID='“.$rs[‚ID‘].“‚“;
    if(hasChildren() funktion($rs[‚ID‘]);
    }
    }

    Hier kann ma nruhig das rekursive anwenden, denn dieses erstellen macht man ja wirklich nur, wenn eine neue Kategorie dazukommt (sollte selten sein, damit sich das lohnt, denn der Neuaufbau wie oben beschrieben, ist natürlich recht aufwändig.

  19. Tobias sagt:

    > GhostGambler sagt
    > am 29. April 2008 @ 08:35
    > Erster Treffer, vierter Post.

    Leider stimmen die Koordinaten nicht mehr – bitte neu angeben oder direkt den Link posten. Danke

  20. Tobias sagt:

    GhostGambler vielen Dank für diese Referenz, die wird sich bestimmt in den nächsten Tagen / Wochen nicht ändern und jeder wird sofort genau das finden was er sucht.

    Nebenbei bemerkt ist diese Lösung nicht praktikabel, da man halt nur eine einfache Unordered List bekommt, die nur eine Unterebene hat. In einem Nested Set sind allerding Unter(Unter…) Ebenen möglich.

    Anders gesagt – das Code Beispiel gibt folgendes aus:
    * Säugetier
    * Primaten
    * Affen
    * Halbaffen
    * Nagetiere

    Und gefragt ist folgende Struktur:
    * Säugetier
    * Primaten
    * Affen
    * Halbaffen
    * Nagetiere

  21. Tobias sagt:

    Okay, das klappt heir nicht – nochmal die Visualisierung:

    Anders gesagt – das Code Beispiel gibt folgendes aus:
    > Säugetier
    > Primaten
    > Affen
    > Halbaffen
    > Nagetiere

    Und gefragt ist folgende Struktur:
    > Säugetier
    >> Primaten
    >>> Affen
    >>> Halbaffen
    >> Nagetiere

  22. Jan sagt:

    Wie gesagt müsst ihr das Auswerten rekursiv machen. Leider habe ich den Code nicht mehr da, da ich es mittlerweile über AJAX löse und nicht mehr das gesamte Menü auf Anhieb lade.

    Aber ich werds mal in nem Beitrag schreiben, wei ich es damals ungefäöhr gemacht habe, da ja anscheinend jede Menge Nachfrage danach besteht.

  23. GhostGambler sagt:

    „im grunde brauchst du in deinem beispiel doch „nur“ jeweils das level vom aktuellen eintrag mit dem vom nächten eintrag vergleichen. in php sind da next() und current() – (arrayfunktionen) deine freunde.

    wenn next dann größer current is, geht n ul auf. wenns kleiner is, ein ul zu. wenns gleich is passiert nüschts…“

    Für mich ist das die Lösung. Kann natürlich sein, dass da jemand anderer Ansicht ist…

  24. Jan sagt:

    Meine Lösung ist ohne next() und current(), ich stell Sie euch bald mal vor. Der Beitrag ist geschrieben, muss aber noch überarbeitet werden.

  25. Lunatic sagt:

    Das Problem mit dem verschieben von ganzen Knoten hatte ich auch und habe gerade diese gute Anleitung zu dem Thema gefunden. Bei mir klappt es damit problemlos, auch wenn ich momentan noch nicht alle Vorgänge nachvollziehen kann. 🙂

  26. Jingles sagt:

    Die erste Query im letzten Listing ist falsch.

    Sie müsste wie bei Arne Klempert zu sehen so lauten:

    DELETE FROM kategorien WHERE lft = $LFT;

  27. Markus sagt:

    Hallo,
    Danke für diese ausführliche Erklärung von Nested Sets, jedoch wollte ich Dich Benachrichtigen, dass deine Annahme, dass es aus Performancegründen sinnvoller wäre den UPDATE query:
    [quote]UPDATE kategorien SET rgt=rgt+2, lft=lft+2 WHERE lft > $RGT;
    UPDATE kategorien SET rgt=rgt+2 WHERE rgt = $RGT;[/quote] so zusammenzufassen aus meiner Sicht auch sinnvoller ist, jedoch nur, wenn der Baum nur 2 Ebenen hat und wenn man mehr Ebenen benötigt, sollte man den query nutzen, den A. Klempert nutzt, da dann das rgt von allen elternelementen (dert ist ) erhöht wird und nicht nur der rgt-wert des direkt darüberliegenden Elternelements.

    Mit freundlichen Grüssen
    Markus

  28. vater sagt:

    BOAH DU HURENSOHN bei mir ist nun die ganze tabelle im arsch wegen:

    db::db_query(„DELETE FROM mainproject.board_category WHERE lft BETWEEN „.$LFT.“ AND „.$RGT);
    db::db_query(„UPDATE mainproject.board_categoryn SET lft=lft-„.$RGT.“-„.$LFT.“+1 WHERE lft>“.$RGT);
    db::db_query(„UPDATE mainproject.board_category SET rgt=rgt-„.$RGT.“-„.$LFT.“+1 WHERE rgt>“.$RGT);

  29. Jan sagt:

    Was heiß „im Arsch“? Dort steht ja, dass diese Befehle zum Löschen einer Kategorie sind. Vermutlich wurde genau das getan, oder?

    Übrigens sollte man nicht gleich jedes Snippet auf seine Produktivumgebung ansetzen.

Eine Antwort schreiben

Ihre E-Mail-Adresse wird nicht veröffentlicht. Benötigte Felder sind markiert mit *

You may use these HTML tags and attributes: <a href=""> <blockquote cite=""> <pre lang=""> <b> <strong> <i> <em>