terça-feira, 2 de outubro de 2012

Achando a chave primária anterior e posterior de uma chave primária existente

Estava eu trabalhando em uma pequena aplicação e o cliente me pediu para acrescentar um recurso onde ele poderia navegar entre os registros um a um. É um esquema muito parecido com grids de dados. Você está no registro número 50 e tem dois botões, um te leva para o registro 49 e outro para o registro 51.

Pensei rapidamente e primeira solução que veio foi obter todos os id's da tabela ordenados e desta forma usando o id atual obter o id imediatamente anterior e o id imediatamente posterior. Lembrando que os id's podem ter "falhas" entre eles, o registro depois do id 25 pode ser o registro de id número 30. Não é uma solução eficiente mas como a aplicação é pequena, vai ser usada por um pequeno número de usuários e aplicando o princípio "Premature Optimization is the root of all Evil" eu decidi deixar assim mesmo.

Mas mais tarde eu voltei a pensar sobre isso: "Puxa vida! Retornar 5000 valores para se usar apenas dois deles?! Deve existir uma solução que seja pelo menos elegante para este problema!". E existe! É possível retornar o id anterior e posterior de um dado id com apenas uma consulta, e aqui está ela:

Que legal! Vai retornar somente o que preciso e não tem problemas com "falhas" entre os valores e caso o valor não exista será retornado NULL. Tudo o que você tem a fazer é passar o id de referência para que possam ser encontrados os valores imediatamente anterior e posterior a ele, neste exemplo eu passei o valor 100 os valores retornados foram 99 e 101.

Eu não fiz nenhum teste de performance sério, mas usando a tabela students do banco de dados do post anterior sobre transações, que tem 5000 registros, a consulta por todos os id's demora em média 92ms no meu computador (o explain da consulta indica uma leitura de todos os registros da tabela como era de se esperar). Esta nova consulta que retorna apenas o que precisamos levou apenas 12ms em média para retornar os resultados. Eu não conheço muito sobre sql ou bancos relacionais, portanto, é bem provável que existam formas melhores de se fazer o que eu fiz, mas espero que este pequeno exemplo possa ajudá-los.

Nenhum comentário:

Postar um comentário