sql >> Databasteknik >  >> RDS >> Mysql

mySQL - Paginering av filtrerade rader

Du kan inte veta vad det första ID:t på en given sida är, eftersom ID-nummer inte nödvändigtvis är sekventiella. Med andra ord kan det finnas luckor i sekvensen, så rader på den femte sidan med 100 rader börjar inte nödvändigtvis på id 500. Det kan till exempel börja på id 527, det är omöjligt att veta.

Ännu ett annat sätt:id är ett värde, inte ett radnummer.

En möjlig lösning om din klient går vidare genom sidor i stigande ordning är att varje REST-begäran hämtar data, noterar den största id-värde på den sidan och använder det i nästa REST-begäran så att den frågar efter id-värden som är större.

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

Men om din REST-begäran kan hämta vilken slumpmässig sida som helst, fungerar inte den här lösningen. Det beror på att du redan har hämtat föregående sida.

En annan lösning är att använda LIMIT <x> OFFSET <y> syntax. Detta gör att du kan begära vilken godtycklig sida som helst. LIMIT <y>, <x> fungerar likadant, men av någon anledning är x och y omvända i de två olika syntaxformerna, så tänk på det.

Använder LIMIT...OFFSET är inte särskilt effektivt när du begär en sida som är många sidor in i resultatet. Säg att du begär den 5 000:e sidan. MySQL måste generera ett resultat på serversidan på 5 000 sidor, sedan kassera 4 999 av dem och returnera den sista sidan i resultatet. Tyvärr, men det är så det fungerar.

Angående din kommentar:

Du måste förstå att WHERE tillämpar villkor för värden i rader, men sidor definieras av positionen av rader. Det här är två olika sätt att bestämma rader!

Om du har en kolumn som garanterat är ett radnummer , då kan du använda det värdet som en radposition. Du kan till och med sätta ett index på den eller använda den som primärnyckel.

Men primärnyckelvärdena kan ändras och kanske inte vara i följd, till exempel om du uppdaterar eller tar bort rader, eller återställer vissa transaktioner och så vidare. Att numrera om primärnyckelvärden är en dålig idé eftersom andra tabeller eller externa data kan referera till primärnyckelvärden.

Så du kan lägga till en annan kolumn som inte är primärnyckeln, men bara ett radnummer.

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

Fyll sedan i värdena när du behöver numrera om raderna.

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

Du måste numrera om raderna om du till exempel tar bort några. Det är inte effektivt att göra detta ofta, beroende på bordets storlek.

Dessutom kan nya inlägg inte skapa korrekta radnummervärden utan att låsa tabellen. Detta är nödvändigt för att förhindra tävlingsförhållanden.

Om du har en garanti för att row_number är en sekvens av på varandra följande värden, då är det både ett värde och en radposition, så du kan använda det för högpresterande indexuppslagningar för valfri sida med rader.

SELECT * FROM MyTable WHERE row_number BETWEEN 401 AND 500;

Åtminstone tills nästa gång sekvensen av radnummer sätts i tvivel genom en radering eller genom nya infogningar.



  1. Kan jag återställa en enskild tabell från en fullständig mysql mysqldump-fil?

  2. Hur gör man behörigheter till en användare på alla nya bord i Postgres?

  3. Kan någon hjälpa till att förklara varför det är dåligt och fel att använda en SQL JOIN?

  4. hur beställer man efter ett dynamiskt kolumnnamn i EntityFramework?