Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

mySQL - Paginação de linhas filtradas


Você não pode saber qual é o primeiro id em uma determinada página, porque os números de id não são necessariamente sequenciais. Em outras palavras, pode haver lacunas na sequência, portanto, as linhas na quinta página de 100 linhas não começam necessariamente no id 500. Pode começar no id 527, por exemplo, é impossível saber.

Dito de outra forma:id é um valor, não um número de linha.

Uma solução possível se o seu cliente estiver avançando pelas páginas em ordem crescente é que cada solicitação REST busca dados, observa o maior id nessa página e, em seguida, use-o no próximo Solicitação REST para consultar valores de id maiores.
SELECT ... FROM ... WHERE filterKey = filterValue 
AND id > id_of_last_match_of_previous_page

Mas se sua solicitação REST puder buscar qualquer página aleatória, essa solução não funcionará. Depende de já ter buscado a página anterior.

Outra solução é usar o LIMIT <x> OFFSET <y> sintaxe. Isso permite que você solicite qualquer página arbitrária. LIMIT <y>, <x> funciona da mesma forma, mas por algum motivo x e y são invertidos nas duas formas de sintaxe diferentes, então tenha isso em mente.

Usando LIMIT...OFFSET não é muito eficiente quando você solicita uma página com muitas páginas no resultado. Digamos que você solicite a página 5.000. O MySQL tem que gerar um resultado no lado do servidor de 5.000 páginas, então descartar 4.999 delas e retornar a última página no resultado. Desculpe, mas é assim que funciona.

Re seu comentário:

Você deve entender que WHERE aplica condições em valores em linhas, mas as páginas são definidas pela posição de filas. Estas são duas maneiras diferentes de determinar linhas!

Se você tiver uma coluna com garantia de número de linha , então você pode usar esse valor como uma posição de linha. Você pode até colocar um índice nele ou usá-lo como chave primária.

Mas os valores da chave primária podem mudar e podem não ser consecutivos, por exemplo, se você atualizar ou excluir linhas, ou reverter algumas transações e assim por diante. Renumerar valores de chave primária é uma má ideia porque outras tabelas ou dados externos podem fazer referência a valores de chave primária.

Então você pode adicionar outra coluna que não a chave primária, mas apenas um número de linha.
ALTER TABLE MyTable ADD COLUMN row_number BIGINT UNSIGNED, ADD KEY (row_number);

Em seguida, preencha os valores quando precisar renumerar as linhas.
SET @row := 0;
UPDATE MyTable SET row_number = (@row := @row + 1) ORDER BY id;

Você teria que renumerar as linhas se excluir algumas, por exemplo. Não é eficiente fazer isso com frequência, dependendo do tamanho da tabela.

Além disso, novas inserções não podem criar valores de número de linha corretos sem bloquear a tabela. Isso é necessário para evitar condições de corrida.

Se você tiver a garantia de que row_number é uma sequência de valores consecutivos, então é um valor e uma posição de linha, para que você possa usá-lo para pesquisas de índice de alto desempenho para qualquer página de linhas arbitrária.
SELECT * FROM MyTable WHERE row_number BETWEEN 401 AND 500;

Pelo menos até a próxima vez que a sequência de números de linha for colocada em dúvida por uma exclusão ou por novas inserções.