Buscar registro anterior e próximo no MySQL

A necessidade é a seguinte: Preciso pegar o id anterior e o próximo id de certo registro em questão; necessário em um blog, por exemplo. Infelizmente não existem no MySQL as funções NEXT() e PREV()… Poderiam existir não é?

Mas, não existindo, me obrigou a pesquisar. Não encontrando nada de bom por aí, me obrigou a pensar e encontrei a solução, utilizando subquerys. Considerando que 2 é o id atual em questão, fica assim:

SELECT * FROM tabela WHERE id = 2 OR id = (SELECT MAX(id) FROM tabela WHERE id < 2) OR id = (SELECT MIN(id) FROM tabela WHERE id > 2)

No caso de serem ids sequenciais, o retorno seriam os dados cujo ids fossem 1, 2 e 3. Se por exemplo o id 3 tivesse sido excluído, o retorno então seria 1, 2 e 4… E assim por diante.

Foi útil para você?

26 comments so far

  1. Marcelo on

    Muito bom.
    Se eu precisar (e algo me diz que vou) já sei onde encontrar 😉

  2. Lucas1 on

    Cara você me salvou!

    Muito obrigado e ate mais.

  3. Jeferson on

    Olá amigo! Preciso, além do id (no meu caso $cdfoto), passar a variável $cdgal para a página… veja se fiz da forma correta:

    $query = “SELECT * FROM foto WHERE cdfoto = 2 AND cdgal=$cdgal OR cdfoto = (SELECT MAX(cdfoto) FROM foto WHERE cdfoto 2 AND cdgal=$cdgal)”;

    Agora a pergunta… como defino as variáveis “anterior” e “próximo”?

    • thiagobfiorenza on

      Olá Jeferson! Verifica se isto resolve teu problema:

      $query = “SELECT * FROM foto WHERE cdgal=$cdgal AND (cdfoto = 2 OR cdfoto = (SELECT MAX(cdfoto) FROM foto WHERE cdfoto < 2) OR cdfoto = (SELECT MIN(cdfoto) FROM foto WHERE cdfoto > 2))”;

      Abraço!

      • Filipi Santana de Assis on

        Poderia fazer assim também:

        SELECT * FROM tabela t WHERE id = 2 OR id = (SELECT MAX(id) FROM tabela WHERE id t.id)

        • thiagobfiorenza on

          Tem certeza que isso funciona Filipi???
          Pra mim não fez sentido algum hehe
          Por acaso você teve problema em postar sua query?

          Abraço!

          • Filipi Santana de Assis on

            Funciona sim, só joguei a query ali para ser sincero hahaha.

            É que assim, como estamos colocando no WHERE da tabela t o campo id = 2, subentende-se que o campo t.id será igual a 2, assim não precisamos repetir o número na subquery.

            Conseguimos evitar falhas humanas com isso também, pois reutilizamos o campo id do primeiro select em todas as consultas dessa query.

            • thiagobfiorenza on

              Oi Filipi… Eu acredito que o que você pensou funciona sim… Mas acho que aconteceu algo no comentário do WordPress… Se você copiar sua query e executá-la vai notar que está com erro de sintaxe…

              Veja em https://thiagobfiorenza.wordpress.com/2011/03/29/buscar-registro-anterior-e-proximo-no-mysql/#comment-55 como resolver este problema…

              Abraço!

              • Filipi Santana de Assis on

                Vamos ver se agora funciona.

                SELECT
                    id,
                        (SELECT
                            MAX(id)
                        FROM
                            tabela
                        WHERE
                            id < t.id) AS maior,
                
                        (SELECT
                            MIN(id)
                        FROM
                            tabela
                        WHERE
                            id > t.id) AS menor
                FROM
                    tabela t
                HAVING id = 2 OR id = maior OR id = menor
                
                • thiagobfiorenza on

                  Agora apareceu!!! \o/

                  É uma ótima solução também!!!

                  Abraço, e obrigado pelo empenho ;D

                  • Thiago Rodrigues on

                    Ola desenterrando o Post rsrs …

                    queria saber como faço para pegar o proximo e anterior soh que nesse caso eu tenho a tabela com os registros e listo eles com alguns sendo destaque e depois o restante . usei o codigo do Filipe e deu certo porem .. tenho registros q sao tipo id 15 outro 50 que estao marcados como destaque como faço pra eles ficarem na sequencia e depois vir normal os outros resultados?

                    rsrs n sei se ficou claro !! rsrs

                    (source language=”sql”)(/source)

  4. willwalker on

    Eu tenho um select melhor:

    SELECT
    atual.id,
    (SELECT MAX(id) FROM imoveis AS anterior WHERE anterior.id atual.id) AS IDproximo
    FROM
    imoveis AS atual

    Abraço

    • willwalker on

      Não sei porque mas não consegui postar a query completa, como uso a tag para SQL?

      • thiagobfiorenza on

        *Obs: Substituir parênteses () por colchetes []. Tive que usar diferente para não converter a sintaxe. Continuando…

        Você deve escrever seu código entre as seguintes tags.

        Para código SQL:
        (source language=”sql”)(/source)

        Para código PHP:
        (source language=”php”)(/source)

        O plugin aceita todas estas linguagens:
        http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/

        Mande-me sua query agora ;D
        Abraços!

        • Walker Sousa on

          Tu frequenta seu blog hein?

          "SELECT *, (SELECT MAX(id) FROM imoveis AS anterior WHERE anterior.id < atual.id AND ativo = ‘1’) AS IDanterior,
          (SELECT MIN(id) FROM imoveis AS proximo WHERE proximo.id > atual.id AND ativo = ‘1’) AS IDproximo FROM imoveis AS atual WHERE ativo = ‘1’"

          Abraços… Nem lembro se era isso, só li a query anterior que postei e procurei em um dos meus ultimos trabalhos.

  5. Thiago on

    Valeu!

  6. Jader on

    assim também funciona, e é mais simples:

    anterior:

    SELECT * FROM tabela WHERE id < 2 ORDER BY id DESC LIMIT 1

    proximo:

    SELECT * FROM tabela WHERE id > 2 ORDER BY id ASC LIMIT 1

  7. Ana on

    Olá Thiago!
    Muito instrutivo o seu blog! Parabéns!
    Estou precisando de orientação da seguinte forma, eu tenho que fazer um cálculo (PHP com MYSQL) em uma determinada tabela que contem

    data km (dados hipotéticos)
    01/03/2012 50
    05/03/2012 89,4
    10/03/2012 133,6
    15/03/2012 190,2

    Preciso que sejam visualizados da seguinte forma:
    Data km_inicial km_final
    05/03/2012 50 89,4
    10/03/2012 89,4 133,6
    15/03/2012 133,6 190,2
    Como eu poderia fazer isso? Poderia me ajudar?
    Desde já agradeço!

  8. miikecruz on

    Adorei a instrução. Muito mais do que útil.

    Estou com um problema, no próximo, ele está pegando sempre o último e não o próximo. O que pode ser?

    “SELECT * FROM ger_portfolio WHERE id_portfolio = ‘$idAqui’ OR id_portfolio = (SELECT MAX(id_portfolio) FROM ger_portfolio WHERE id_portfolio ‘$idAqui’)”;

  9. Michel on

    Consegui fazer no PDO orientado a objeto… rodou 100%… grato

  10. matheusafonso on

    Massa! Precisei usar pra fazer um sisteminha e rodou show de bola!
    Obrigado por compartilhar conosco!!

  11. Lucas Anaia on

    prepare(‘SELECT tipo,categoria,id,titulo FROM post WHERE ‘.$string_url_type_nId.’ ORDER BY id ASC’);
    $f->bindParam(‘:curso’,$a);
    $f->bindParam(‘:cat’,$b);
    $g = false;
    $h = null;
    $post_anterior = null;
    if ($f->execute()) {
    if ($f->rowCount() > 0 ) {
    $g = true;
    $sql_count = 4;
    $h = $f->fetchAll();
    $a_ = 0;
    $b_ = 1000;
    while ( $a_ < $b_ ) {
    // se não existir, para o loop
    if ( ! isset( $h[$a_][2] ) ) {
    break;
    }
    // post atual
    if ( $h[$a_][2] == $c ) {
    // post anterior
    if ( isset ( $h[$a_ – 1][2] ) )
    for ($c_ = 0; $c_
    <a href="”>

    Esse é o primeiro post 🙂

    Para usar o proximo post e o mesmo esquema de cima, usando explode.

  12. Lucas Anaia on

    CODIGO DE CIMA TA AQUI ->
    http://codepad.org/8fCOffus . boa sorte 🙂


Deixar mensagem para willwalker Cancelar resposta