Tach!
Ich habe jetzt nur die ID 30
Ab dieser ID als Aufsetzpunkt soll ich 5 Datensätze ausgeben in der Sortierung nach name,id
Wie kann ich das möglichst in einer einzigen Abfrage bewerkstelligen?
Ich glaube nicht, dass das ohne Stored Procedure geht, bei der du dich durch die sortierte Ergebnismenge hangelst und alles bis zum Auftreten der ID verwirfst, ab dann alles in eine temporäre Tabelle einfügst, die du dann zum Schluss ausgibst.
Da fällt mir noch eine weitere Lösung mit einer Variable ein, die zunächst auf NULL gesetzt wird. In einem SELECT mit IF() oder CASE prüfst du auf deine ID, setzt daraufhin deine Variable mit diesem Wert (oder was anderem, das TRUE entspricht). Das ist auch das eine Teilergebnis des Ausdrucks. Der Else-Zweig gibt NULL zurück. Dieses IF/CASE kommt als zweiter Ausdruck in ein COALESCE(). Der erste Ausdruck ist die Variable. Das Ergebnis von COALESCE() wertest du boolesch aus und selektierst so deine Datensätze aus einer sortiert vorliegenden Menge (die wird aus einem Subselect kommen müssen). Solange die Variable immer noch NULL ist, wird der zweite Audruck ausgewertet, bei dem auf die ID getestet und gegebenenfalls die Variable entNULLT wird. Das Ergebnis ist also entweder kein NULL bei der gesuchten ID oder NULL, und der Datensatz wird genommen oder nicht. Danach zieht die Variable (mit != NULL) im ersten Parameter und der Datensatz wird genommen.
Das Handbuch rät davon zwar ab: "As a general rule, you should never assign a value to a user variable and read the value within the same statement. You might get the results you expect, but this is not guaranteed.", aber ich kann mir vorstellen, dass durch die Verschachtlung die Verarbeitungsreihenfolge eindeutig wird. Es darf nur nicht irgendein Index die Reihenfolge ändern. Das sollte eigentlich nicht vorkommen und MySQL müsste bei diesem Vergleich immer einen Full Table Scan auf die Subselect-Menge anwenden (was sich mit einem EXPLAIN prüfen lassen sollte[1]). Das ist dann auch der Nachteil an beiden Lösungsansätzen: performant wirst du das bei großen Datenmengen nicht bekommen, weil MySQL immer zu Fuß durch die Datenmenge laufen muss.
Nicht dass ich in meiner Prosa einen Fehler drin habe, deswegen hier in Codeform, wie ich mir das denke:
SET @marker = NULL;
SELECT * FROM (SELECT * FROM tabelle ORDER BY name) WHERE COALESCE(@marker, IF(id=30, @marker := 1, NULL))
Erklärungsversuch, warum es nicht bereits eine Funktion gibt, die bis zu oder ab einem bestimmten Merkmal alles nimmt: MySQL arbeitet (wie eigentlich alle SQL-Systeme) mit Datenmengen ohne definierte Reihenfolge. Es ist nicht unbedingt vorhersehbar, ob der Optimierer einen Index nimmt oder nicht, so dass die Reihenfolge nicht feststeht, in der er die Datensätze auswertet. Und das macht es im Prinzip unmöglich, eine solche Funktion mit deterministischem Ergebnis zu schreiben. Die Variablen-Lösung geht davon aus (die andere eigentlich auch), dass man die Suchreihenfolge festgelegt bekommt.
[1] Zu prüfen wäre, dass kein Index _verfügbar_ ist. Wenn nur keiner genommen wird, heißt das nicht, dass das immer so bleibt. Der Ausführungsplan ändert sich auch mit der Anzahl der Datensätze.
dedlfix.