Mysql
 sql >> база данни >  >> RDS >> Mysql

mySQL - Страниране на филтрирани редове

Не можете да знаете кой е първият идентификатор на дадена страница, защото номерата на идентификаторите не са непременно последователни. С други думи, може да има пропуски в последователността, така че редовете на петата страница от 100 реда не започват непременно с id 500. Може да започват с id 527 например, това е невъзможно да се знае.

Изразено по друг начин:id е стойност, а не номер на ред.

Едно възможно решение, ако клиентът ви преминава през страници във възходящ ред, е всяка REST заявка да извлича данни, отбелязва най-големият id стойност на тази страница, след което я използва в следващата REST искане, така че заявява по-големи стойности на id.

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

Но ако вашата REST заявка може да извлече произволна страница, това решение не работи. Зависи дали вече сте извлекли предишната страница.

Друго решение е да използвате LIMIT <x> OFFSET <y> синтаксис. Това ви позволява да заявите произволна страница. LIMIT <y>, <x> работи по същия начин, но по някаква причина x и y са обърнати в двете различни синтактични форми, така че имайте това предвид.

Използване на LIMIT...OFFSET не е много ефективен, когато поискате страница, която е много страници в резултата. Да кажем, че поискате 5000-та страница. MySQL трябва да генерира резултат от страната на сървъра от 5000 страници, след това да отхвърли 4999 от тях и да върне последната страница в резултата. Съжалявам, но така става.

Re your comment:

Трябва да разберете това WHERE прилага условия към стойности в редове, но страниците се определят от позицията от редове. Това са два различни начина за определяне на редове!

Ако имате колона, която гарантирано е номер на ред , тогава можете да използвате тази стойност като позиция на ред. Можете дори да поставите индекс върху него или да го използвате като първичен ключ.

Но стойностите на първичния ключ може да се променят и може да не са последователни, например ако актуализирате или изтриете редове или върнете някои транзакции и т.н. Преномерирането на стойностите на първичния ключ е лоша идея, защото други таблици или външни данни може да препращат към стойностите на първичния ключ.

Така че можете да добавите друга колона, която не е първичен ключ, но само номер на ред.

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

След това попълнете стойностите, когато трябва да преномерирате редовете.

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

Ще трябва да преномерирате редовете, ако някога изтриете някои, например. Не е ефективно да правите това често, в зависимост от размера на таблицата.

Освен това новите вмъквания не могат да създават правилни стойности на номера на редове, без да заключат таблицата. Това е необходимо за предотвратяване на условия за състезание.

Ако имате гаранция, че row_number е поредица от последователни стойности, тогава е едновременно стойност и позиция на ред, така че можете да го използвате за високоефективни индексни търсения за всяка произволна страница от редове.

SELECT * FROM MyTable WHERE row_number BETWEEN 401 AND 500;

Поне до следващия път, когато поредицата от номера на редове бъде поставена под съмнение чрез изтриване или нови вмъквания.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Съхранение на IPv6 адреси в MySQL

  2. Може ли MySQL да замени няколко знака?

  3. Spring-Hibernate, използвайки множество източници на данни/база данни

  4. Как да съхранявате данни, чийто тип може да бъде число, дата или низ в mysql

  5. MySQL БРОЙ на множество леви съединения - оптимизация