0Pricing
Coding Interview Prep · Aula

Mantendo a linha mais recente por chave

Use o padrão de registro mais recente por cliente, particionando pela chave e ordenando pela data.

Mantendo a linha mais recente por chave é uma aula grátis de Coding Interview Prep no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Coding Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Coding Interview Prep inclui 4 aulas no total.

A questão do registro mais recente por chave

"Retorne o pedido mais recente de cada cliente." "Obtenha o estado mais recente de cada dispositivo." Esse problema de registro mais recente por chave é uma das tarefas de entrevista de SQL mais frequentes, pois aparece constantemente no trabalho real de análise de dados.

Trata-se de um caso especializado de primeiro registro por grupo: particione pela chave, ordene pelo carimbo de data/hora em ordem decrescente e mantenha a primeira linha. Esta lição aprofunda o padrão e suas alternativas.

Por que MAX sozinho não é suficiente

Uma resposta inicial tentadora é MAX(order_date) agrupado por cliente. Isso fornece a data mais recente, mas não o restante da linha desse pedido, o identificador do pedido, o valor ou o estado.

Se o entrevistador quiser a linha completa mais recente, MAX com GROUP BY precisa de uma junção adicional de volta à tabela pela chave e pela data máxima, o que é verboso e pode falhar em caso de empate. As funções de janela são mais simples.

-- Gives the date, not the full row
SELECT customer_id, MAX(order_date) AS last_order
FROM orders
GROUP BY customer_id;

O padrão ROW_NUMBER

Particione pela chave, ordene pelo carimbo de data/hora em ordem decrescente, e a linha mais recente receberá rn = 1. Mantenha apenas essas linhas e você terá o registro completo mais recente por chave.

Esta é a resposta padrão. Ela retorna exatamente uma linha por chave mesmo quando os carimbos de data/hora empatam, o que geralmente está implícito em "a linha mais recente".

WITH ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id
      ORDER BY order_date DESC
    ) AS rn
  FROM orders
)
SELECT customer_id, order_id, order_date, amount
FROM ranked
WHERE rn = 1;

Tratando empates de carimbo de data/hora

Dois pedidos do mesmo cliente podem compartilhar um order_date (o mesmo dia ou carimbos de data/hora idênticos). Sem um critério de desempate, qual deles se torna rn = 1 é arbitrário e pode mudar entre execuções.

Adicione uma chave secundária única, como order_id DESC, para que a linha mais recente seja determinada de forma inequívoca. Os entrevistadores verificam especificamente se você percebeu esse caso-limite.

ROW_NUMBER() OVER (
  PARTITION BY customer_id
  ORDER BY order_date DESC, order_id DESC
) AS rn

Mais recente versus todos os empates

Decida o que "mais recente" significa quando os carimbos de data/hora empatam:

  • Se quiser exatamente uma linha por chave → use ROW_NUMBER com um critério de desempate.
  • Se quiser todas as linhas que compartilham o carimbo de data/hora máximo → use RANK() = 1, que retorna todas as linhas mais recentes empatadas.

Fazer essa pergunta de esclarecimento demonstra que você entende a semântica, não apenas a sintaxe.

WITH ranked AS (
  SELECT *,
    RANK() OVER (
      PARTITION BY customer_id ORDER BY order_date DESC
    ) AS rnk
  FROM orders
)
SELECT * FROM ranked WHERE rnk = 1;

A alternativa da subconsulta correlacionada

Antes que as funções de janela fossem universais, a resposta para o registro mais recente por chave usava uma subconsulta correlacionada: mantenha uma linha apenas se nenhuma outra linha da mesma chave tiver uma data maior.

Ela funciona, mas executa a consulta interna para cada linha, portanto é mais lenta em tabelas grandes e complicada em caso de empate. Mencione-a para demonstrar conhecimento das alternativas, mas prefira a resposta com função de janela por motivos de desempenho.

SELECT o.*
FROM orders o
WHERE o.order_date = (
  SELECT MAX(o2.order_date)
  FROM orders o2
  WHERE o2.customer_id = o.customer_id
);

Atalho DISTINCT ON do PostgreSQL

O PostgreSQL oferece uma forma concisa: DISTINCT ON (key) mantém a primeira linha de cada chave de acordo com a ORDER BY. A ORDER BY deve começar pelas mesmas colunas da chave e, em seguida, pelo critério de desempate e pelo carimbo de data/hora.

É elegante e rápido no PostgreSQL, mas não é portável. Cite-o como um recurso adicional específico do dialeto, mantendo ROW_NUMBER como padrão portável.

SELECT DISTINCT ON (customer_id)
  customer_id, order_id, order_date, amount
FROM orders
ORDER BY customer_id, order_date DESC, order_id DESC;

Registro mais recente com uma condição

Perguntas reais adicionam filtros: "o pedido concluído mais recente por cliente". Aplique o filtro antes da classificação para que apenas as linhas qualificadas sejam numeradas.

Coloque a condição no WHERE da consulta interna (ela é executada antes da função de janela) e depois selecione rn = 1 na consulta externa. Filtrar depois da classificação retornaria a linha errada.

WITH ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id ORDER BY order_date DESC, order_id DESC
    ) AS rn
  FROM orders
  WHERE status = 'completed'
)
SELECT * FROM ranked WHERE rn = 1;

Exemplo resolvido: estado mais recente do dispositivo

Uma tabela status_log registra device_id, status e logged_at. Para obter o estado atual de cada dispositivo, particione por device_id, ordene por logged_at DESC e mantenha rn = 1.

Esse é o mecanismo por trás de painéis que mostram o "estado atual" de muitas entidades a partir de um registro de eventos somente para inclusão. A mesma receita permite consultas de preço mais recente, localização mais recente e versão mais recente.

WITH latest AS (
  SELECT device_id, status, logged_at,
    ROW_NUMBER() OVER (
      PARTITION BY device_id ORDER BY logged_at DESC
    ) AS rn
  FROM status_log
)
SELECT device_id, status, logged_at
FROM latest
WHERE rn = 1;

Observações de desempenho

Pontos que demonstram senioridade:

  • Um índice em (customer_id, order_date DESC) permite que o mecanismo leia a linha mais recente de cada chave com eficiência.
  • A abordagem com janela percorre a tabela uma vez; a subconsulta correlacionada não.
  • DISTINCT ON no PostgreSQL pode usar o mesmo índice e costuma ser a opção mais rápida para uma única tabela.
  • Para registros de eventos com muitas inclusões, considere uma tabela materializada de registros mais recentes, atualizada incrementalmente.

Erros comuns

Preste atenção a estes pontos:

  • Usar MAX(date) e retornar apenas a data, não a linha completa.
  • Esquecer o critério de desempate, produzindo resultados não determinísticos quando as datas empatam.
  • Filtrar pela condição depois da classificação, o que pode escolher uma linha que deveria ter sido excluída.
  • Confundir "uma única linha mais recente" (ROW_NUMBER) com "todas as linhas mais recentes empatadas" (RANK).

Verificação rápida

Escolha a consulta correta para obter o registro mais recente por chave.

Resumo: registro mais recente por chave

O padrão: PARTITION BY chave, ORDER BY carimbo de data/hora DESC (mais um critério de desempate único), mantenha rn = 1.

  • MAX(date) fornece a data, não a linha completa.
  • Sempre adicione um critério de desempate para garantir o determinismo.
  • Use RANK() = 1 se quiser todas as linhas empatadas no carimbo de data/hora mais recente.
  • As condições de filtro devem ficar na consulta interna, antes da classificação.
  • DISTINCT ON do PostgreSQL é uma alternativa concisa e rápida específica do dialeto.

Perguntas Frequentes

A aula “Mantendo a linha mais recente por chave” é grátis?

Sim — o texto completo de “Mantendo a linha mais recente por chave” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Coding Interview Prep, atualize para CoddyKit PRO. O curso de Coding Interview Prep inclui 4 aulas no total.

O que vou aprender em “Mantendo a linha mais recente por chave”?

Use o padrão de registro mais recente por cliente, particionando pela chave e ordenando pela data. Você pratica Coding Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Coding Interview Prep?

Nenhuma experiência prévia é necessária. Coding Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Mantendo a linha mais recente por chave”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Coding Interview Prep?

Sim. Cada aula de Coding Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Linhas Top-N por grupo com ROW_NUMBER
  2. Lidando com empates em Top-N
  3. Eliminando duplicatas de linhas com segurança
  4. Mantendo a linha mais recente por chave
← Voltar para Coding Interview Prep