Hallo Ilja,
Eher verwundert mich, dass er nur eine Join-Bedingung aber vier Tabellen/Aliase hat. Oder zählen die beiden BETWEEN-Bedingunen zu den JOIN-Bedingungen und nicht zu den datensatzeinschränkenden? Das Hauptproblem ist ja, dass er hier wohl irgendwelche riesigen kartesischen Produkte bekommt, weil er nicht richtig verknüpft und/oder einschränkt.
ja, und deswegen auch die explizite schreibweise, die bringt sowas immer sehr schnell ans tageslicht.
Du sagst ja gerne "Joins sind böse.". Ist dies hier nicht der Fall - und vielleicht nur MySQLs hoher Verbreitung und ehemaliger Subselect- und SP-Unfähigkeit geschuldet?
Wenn ich mir das von mir umgeschriebene
SELECT
node.payload
FROM
000node parent
INNER JOIN
000node node
ON
node.lft BETWEEN parent.lft AND parent.rgt
WHERE
parent.payload = 5895
ORDER BY
node.lft;
ansehe, so ist es in Wirklichkeit gar kein Join, sondern durch folgende Statements ersetzbar:
SELECT
lft,
rgt
FROM
000node
WHERE
<bedingungen, die Ausgangsknoten eindeutig identifizieren>;
Wenn es genau einen Datensatz gibt, fülle die Variablen lower und upper mit den Werten aus lft bzw. rgt. und gebe anschließend das Resultset von
SELECT
kommagetrennte,
liste,
gewünschter,
spalten
FROM
000node
WHERE
lft BETWEEN upper AND lower
zurück, was über eine SP problemlos machbar sein sollte. MySQLs SELECT ... INTO unterstützt das Füllen von Variablen, die man anschließend in einem serverseitigen Prepared Statement nutzen könnte (kein dynamisches SQL in einer SP in MySQL).
alternativ:
SELECT
node.payload
FROM
000node node
WHERE
node.lft BETWEEN (SELECT
parent.lft
FROM
000node parent
WHERE
parent.payload = 5895
)
AND (SELECT
parent.rgt
FROM
000node parent
WHERE
parent.payload = 5895
)
in der Hoffnung, dass der Optimizer merkt, dass er die Subselects nur einmal auszuführen braucht (und zwei Subselects, wo mir eines lieber wäre, aber mir fällt gerade nichts ein, womit ich dieses umgehen könnte). Andere DBMS kennen ja eine WITH-Klausel, die man für genau solche Zwecke wunderbar nutzen könnte.
Freundliche Grüße
Vinzenz