Mysql
 sql >> Datenbank >  >> RDS >> Mysql

mySQL - Paginierung gefilterter Zeilen

Sie können nicht wissen, was die erste ID auf einer bestimmten Seite ist, da ID-Nummern nicht unbedingt fortlaufend sind. Mit anderen Worten, es könnte Lücken in der Sequenz geben, sodass Zeilen auf der fünften Seite von 100 Zeilen nicht unbedingt bei ID 500 beginnen. Sie könnten beispielsweise bei ID 527 beginnen. Es ist unmöglich zu wissen.

Noch anders ausgedrückt:id ist ein Wert, keine Zeilennummer.

Eine mögliche Lösung, wenn Ihr Client in aufsteigender Reihenfolge durch Seiten vorrückt, besteht darin, dass jede REST-Anforderung Daten abruft, bemerkt der größte id-Wert auf dieser Seite und verwendet diesen dann in der nächsten REST-Anforderung, sodass größere ID-Werte abgefragt werden.

SELECT ... FROM ... WHERE filterKey = filterValue 
AND id > id_of_last_match_of_previous_page

Wenn Ihre REST-Anforderung jedoch eine beliebige Seite abrufen kann, funktioniert diese Lösung nicht. Es hängt davon ab, ob die vorherige Seite bereits abgerufen wurde.

Eine andere Lösung ist die Verwendung von LIMIT <x> OFFSET <y> Syntax. Damit können Sie jede beliebige Seite anfordern. LIMIT <y>, <x> funktioniert genauso, aber aus irgendeinem Grund sind x und y in den beiden unterschiedlichen Syntaxformen vertauscht, also behalte das im Hinterkopf.

Verwenden von LIMIT...OFFSET ist nicht sehr effizient, wenn Sie eine Seite anfordern, die viele Seiten im Ergebnis enthält. Angenommen, Sie fordern die 5.000. Seite an. MySQL muss auf der Serverseite ein Ergebnis von 5.000 Seiten generieren, dann 4.999 davon verwerfen und die letzte Seite im Ergebnis zurückgeben. Entschuldigung, aber so funktioniert es.

Zu Ihrem Kommentar:

Sie müssen dieses WHERE verstehen wendet Bedingungen auf Werte an in Zeilen, aber Seiten werden durch die Position definiert von Reihen. Dies sind zwei verschiedene Möglichkeiten, Zeilen zu bestimmen!

Wenn Sie eine Spalte haben, die garantiert eine Zeilennummer ist , dann können Sie diesen Wert wie eine Zeilenposition verwenden. Sie können ihm sogar einen Index hinzufügen oder ihn als Primärschlüssel verwenden.

Primärschlüsselwerte können sich jedoch ändern und sind möglicherweise nicht fortlaufend, z. B. wenn Sie Zeilen aktualisieren oder löschen oder einige Transaktionen rückgängig machen und so weiter. Primärschlüsselwerte neu zu nummerieren ist eine schlechte Idee, da andere Tabellen oder externe Daten möglicherweise auf Primärschlüsselwerte verweisen.

Sie könnten also eine weitere Spalte hinzufügen, die nicht ist der Primärschlüssel, sondern nur eine Zeilennummer.

ALTER TABLE MyTable ADD COLUMN row_number BIGINT UNSIGNED, ADD KEY (row_number);

Füllen Sie dann die Werte aus, wenn Sie die Zeilen neu nummerieren müssen.

SET @row := 0;
UPDATE MyTable SET row_number = (@row := @row + 1) ORDER BY id;

Sie müssten beispielsweise die Zeilen neu nummerieren, wenn Sie jemals welche löschen. Abhängig von der Größe der Tabelle ist es nicht effizient, dies häufig zu tun.

Außerdem können neue Einfügungen keine korrekten Zeilennummernwerte erstellen, ohne die Tabelle zu sperren. Dies ist notwendig, um Rennbedingungen zu verhindern.

Wenn Sie eine Garantie dafür haben, dass row_number eine Folge aufeinanderfolgender Werte ist, dann ist es sowohl ein Wert als auch eine Zeilenposition, sodass Sie es für leistungsstarke Indexsuchen für jede beliebige Seite von Zeilen verwenden können.

SELECT * FROM MyTable WHERE row_number BETWEEN 401 AND 500;

Zumindest bis zum nächsten Mal, wenn die Reihenfolge der Zeilennummern durch eine Löschung oder durch neue Einfügungen in Frage gestellt wird.