NestedSets - Menüpfad
johanoa
- datenbank
0 Frank (no reg)0 Bademeister0 johanoa0 johania0 Vinzenz Mai0 johanoa
0 Frank (no reg)
Hallo,
ich habe eine NestedSets-Tabelle mit left / right / level
Nun habe ich ein Wertetripel gegeben und möchte dazu folgende Datesätze ausgeben:
Dies soll eine Navigation abgeben, die die relevanten Teile aufklappt.
Beispiel:
Sollte ausgegeben werden, wenn ich mich bei "ich" befinde.
Bisjetz habe ich einfach immer den kompletten Baum ausgelesen, was aber auch nicht schön ist.
Also habe ich es mit
SELECT p.*
FROM tree n,
tree p
WHERE n.lft BETWEEN p.lft AND p.rgt
AND n.id = 5
ORDER BY n.lft;
probiert. Hier fehlen mit natürlich die Geschwister jedes Knotenpunktes auf dem Pfad und die direkten Kinder.
Hat mir jemand einen Rat?
Gruß
Hi,
Geschwister eines Knotenpunktes haben immer eine markante Gemeinsamkeit: Right grenzt an Left. Ausserdem brauchst du UNION.
Vielleicht solltest du dir das ganze mal in einem Diagramm visualisieren, wie die Werte genau aussehen in so einem Nested Set Baum mit mehreren Ebenen. Selbst mit einem Auge solltest du da gewisse Muster erkennen können.
Gruss, Frank
Hallo,
Hallo johanoa
ich habe eine NestedSets-Tabelle mit left / right / level
Das Level solltest Du nicht speichern, das ist redundant und kann relativ leicht berechnet werden.
Nun habe ich ein Wertetripel gegeben und möchte dazu folgende Datesätze ausgeben:
- Die Kinder eine Ebene tiefer als der gegebene Knotenpunkte.
- Die Geschwister zu jedem Knotenpunkt auf dem Pfad
was meinst Du mit dem zweiten Punkt genau?
Ich hätte das so verstanden, dass von dem "ich" aus nur
- bin
- ich
- mit
- ein paar
- unterpunkten
ausgegeben werden soll. Oder stimmt das nicht?
SELECT p.*
FROM tree n,
tree p
WHERE n.lft BETWEEN p.lft AND p.rgt
AND n.id = 5
ORDER BY n.lft;
Das ist glaub ich nicht, was Du willst. Das gibt Dir nämlich alle Vorfahren Deines Knotens mit id 5. Du brauchst eher sowas
SELECT n.id, count(*) -- das Zweite gibt Dir das Level, ggf. auch count(*) - 1
FROM tree n,
tree p
WHERE n.lft BETWEEN p.lft AND p.rgt
AND n.level = (das Level des knotens "ich" oder eins kleiner) -- in die Klammern muss ne entsprechende Unterabfrage)
ORDER BY n.lft;
Oder?
Viele Grüße
der Bademeister
Hi Bademeister,
ich habe eine NestedSets-Tabelle mit left / right / level
Das Level solltest Du nicht speichern, das ist redundant und kann relativ leicht berechnet werden.
Und wenn schon, die Persistierung dieser Information reduziert den "Berechnungs-"Aufwand bei globalen Abfragen auf den gesamten Baum durchaus signifikant. Vorallem, wenn man Datenbanksysteme hat, die keine Subqueries vertragen. Das Level als persistierte Information ist ein guter alternativer Eintrittspunkt in die Baumstruktur.
CIao, Frank
Hi Frank,
Und wenn schon, die Persistierung dieser Information reduziert den "Berechnungs-"Aufwand bei globalen Abfragen auf den gesamten Baum durchaus signifikant.
... macht aber das Einfügen von Knoten in ca. gleichem Maße aufwendiger. Klar, im Falle dieses Menüs wird wohl nicht allzu oft was geändert, aber es ist natürlich auch nicht sehr groß, daher ist auch der Rechenaufwand durch das Berechnen des Levels hier recht klein.
Vorallem, wenn man Datenbanksysteme hat, die keine Subqueries vertragen.
Wenn dem hier so ist, dann wäre das natürlich ein Problem, das stimmt.
Also, Johanna, ich ziehe meine Empfehlung, Du sollest das Level nicht speichern, zurück und mache daraus nur den Hinweis, dass Du es nicht zwingend speichern musst, weil Du es berechnen kannst (wobei Du für Vergleiche von Leveln allerdings Subqueries brauchst).
Viele Grüße an alle
der Bademeister
Hallo,
also, dass ich die Ebene mitspeichere habe ich bewusst entschieden.
left grenzt an right erscheint mir logisch nur muss ich ja jetzt irgendwie in der Abfrage formulieren, dass jeder Knotenpunkt auf dem Weg zum aktuellen left-Wert (auch Knotentpunkt 1) nach diesen Geschwistern durchgegangen wird. Mir fehlt etwas die Idee.
Mit
SELECT p.*
FROM tree AS n
INNER JOIN tree AS p
ON (n.left BETWEEN p.left AND p.right
AND (n.left = '12' OR n.level = '1'))
GROUP BY p.left
Bekomme ich alle Knoten der ersten Ebene, dies sind ja praktisch die Geschwister des ersten Knotenpunktes.
Und ich bekomme den aktuellen Knoten selbst.
Doch wie muss ich das jetzt anpacken, dass ich auf dem Weg dorthin die jeweiligen Geschwister möchte, die mit ihrem left an den right grenzen?
Gruß
Hallo,
ich könnte auch den Pfad bis zum Knoten in einer ersten Abfrage herausfinden, sodass ich alle left- und right-Werte des Pfades bis zum aktuellen Knoten habe.
Dann könnte ich für jedes left-right-Paar die Kinder, die höchstens eine Ebene tiefer liegen Abfragen.
Aber dann benötige ich ja mehrere Abfragen, das kanns ja auch nicht sein.
Ist es eventuell einfacher den Teilbaum beim umsetzen der Daten in eine Navigation umzusetzen? Jedoch würde mir auch hier die Idee, fehlen.
Gruß
Hallo,
ich könnte auch den Pfad bis zum Knoten in einer ersten Abfrage herausfinden, sodass ich alle left- und right-Werte des Pfades bis zum aktuellen Knoten habe.
nicht in einer ersten :-)
a) Hast Du eine Abfrage, die Dir die Geschwister eines Knotens liefert?
b) Noch besser wäre eine Abfrage, die Dir die Geschwister eines Knotens und den
Knoten selbst liefert.
Gehen wir von a) aus:
Gib mir die
Geschwisterknoten
und ihr Level
aller Knoten,
die im Pfad des ausgewählten Knotens liegen (Subselect!)
Verbinde dieses Ergebnis mit (UNION)
Gib mir die
Knoten
und ihr Level
aller Knoten,
die im Pfad des ausgewählten Knotens liegen
Bei b) kannst Du auf die UNION verzichten:
Gib mir
die Knoten und ihre Geschwister,
sowie ihr Level
aller Knoten
die im Pfad des ausgewählten Knotens liegen
Sollte doch machbar sein.
Freundliche Grüße
Vinzenz
Hallo,
danke für deine Ausführungen.
Nein ich habe keine Abfrage, die mir die Geschwister liefert. Da felht mir das Verständnis. Geschwister-left grenz an Aktuell-right und Geschwister-right an Aktuell-left währen die Ebene gleich sein muss. Aber das bekomme ich nicht abgefragt.
Bis jetzt habe ich eine Abfrage, die mir den Pfad liefert (der angesprochene Subselect).
Und eine Abfrage, die die direkten Kinder zu einem Knoten liefert.
Diese zwei Abfragen verbinde ich aktuell für mein Vorhaben.
Ich komme nicht dahinter, wie ich die Geschwister abfragen könnte.
Gruß
Hallo,
Bis jetzt habe ich eine Abfrage, die mir den Pfad liefert (der angesprochene Subselect).
Und eine Abfrage, die die direkten Kinder zu einem Knoten liefert.
Diese zwei Abfragen verbinde ich aktuell für mein Vorhaben.
ja, so geht es auch:
Gib mir
die direkten Kinder
der Knoten,
die sich im Pfad des aktuellen Knotens befinden
und nicht der aktuelle Knoten selbst sind
(weil es Deine Anforderung ist, dass die Kinder des aktuellen Knotens nicht angezeigt werden)
Freundliche Grüße
Vinzenz
Hi,
Mir fehlt etwas die Idee.
Und mir fehlt langsam der Durchblick.Mach doch bitte mal endlich ne Zeichnung (möglichst nah an der Realität)
Von der Zeichnung machst n Screenshot, lädst es auf irgendeinen Bilderhoster im Web hoch und verlinkst es hier. Dann kann man dir vielleicht gezielter helfen. Man sagt ja auch: Ein Bild sagt mehr als tausend Worte.
Nebenbei: Unterabfragen (Subqueries) versteht dein Datenbanksystem? Und dein Datenbanksystem ist welches _genau_?
Ciao, Frank