0Pricing
SQL Interview Prep · Aula

Filtrando um resultado de janela

Entenda por que é necessário envolver uma função de janela em uma subconsulta ou CTE para filtrá-la.

Filtrando um resultado de janela é uma aula grátis de SQL 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 SQL Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Interview Prep inclui 4 aulas no total.

Por que não é possível filtrar uma janela em WHERE

Uma "pegadinha" frequente em entrevistas: escrever WHERE ROW_NUMBER() OVER (...) = 1 gera um erro. As funções de janela não são permitidas em WHERE, GROUP BY ou HAVING.

O motivo é a ordem lógica de execução. WHERE é executado para selecionar linhas antes que as funções de janela sejam avaliadas. A janela ainda nem foi calculada, portanto não pode ser referenciada em um filtro.

A explicação da ordem de execução

As funções de janela são calculadas em uma fase dedicada que ocorre depois de FROM, WHERE, GROUP BY e HAVING, mas antes do ORDER BY e do LIMIT finais.

Assim, no momento em que WHERE é executado, a classificação ou o número da linha ainda não existe. Para filtrá-lo, é necessário deixar a janela terminar primeiro e, depois, filtrar a coluna produzida em uma camada de consulta externa.

O padrão de encapsulamento com subconsulta

A correção padrão é calcular a função de janela em uma consulta interna (uma tabela derivada), atribuir um nome ao resultado e depois filtrar esse nome alternativo no WHERE externo.

A tabela derivada deve ter um nome alternativo (t aqui) — os entrevistadores observam os candidatos que se esquecem disso. Agora rn é uma coluna comum que a consulta externa pode comparar.

SELECT *
FROM (
  SELECT
    name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
  FROM employees
) t
WHERE rn = 1;

O padrão com CTE (geralmente mais claro)

Uma Expressão de Tabela Comum faz o mesmo trabalho com uma estrutura mais legível. Defina a classificação em uma etapa WITH e depois filtre-a na consulta principal.

Funcionalmente, é idêntica à subconsulta, mas os entrevistadores geralmente preferem CTEs em exercícios de programação ao vivo, porque a intenção pode ser lida de cima para baixo.

WITH ranked AS (
  SELECT
    name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
  FROM employees
)
SELECT name, department, salary
FROM ranked
WHERE rn = 1;

Exemplo resolvido: N primeiros por grupo

O problema de janela mais comum é: "3 funcionários mais bem pagos por departamento". Calcule a classificação dentro da CTE e mantenha rn <= 3 do lado de fora.

Escolha a função de classificação de acordo com o comportamento dos empates: ROW_NUMBER limita a exatamente 3 linhas por departamento; alterne para RANK/DENSE_RANK se os empates no limite precisarem ser incluídos.

WITH ranked AS (
  SELECT department, name, salary,
         ROW_NUMBER() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS rn
  FROM employees
)
SELECT department, name, salary
FROM ranked
WHERE rn <= 3
ORDER BY department, rn;

Exemplo resolvido: filtrando um total acumulado

O padrão de encapsulamento não serve apenas para classificações. Qualquer resultado de janela — totais acumulados, médias móveis, diferenças de LAG — deve ser filtrado da mesma forma.

Aqui, calculamos um saldo acumulado e depois mantemos apenas as linhas em que ele ultrapassou 1000 pela primeira vez. O filtro fica fora da camada da janela.

WITH balances AS (
  SELECT
    account_id, txn_date, amount,
    SUM(amount) OVER (
      PARTITION BY account_id ORDER BY txn_date
    ) AS running_balance
  FROM transactions
)
SELECT *
FROM balances
WHERE running_balance > 1000;

QUALIFY: o atalho em alguns bancos de dados

Snowflake, BigQuery, Teradata e DuckDB oferecem uma cláusula QUALIFY que filtra diretamente os resultados de janela — sem necessidade de encapsulamento. Ela é executada depois das funções de janela, exatamente no ponto desejado.

Mencione QUALIFY para demonstrar amplitude, mas observe que ele não faz parte do SQL padrão e não existe em PostgreSQL, MySQL e SQL Server, nos quais ainda é necessário usar a subconsulta/CTE.

-- Snowflake / BigQuery only:
SELECT department, name, salary
FROM employees
QUALIFY ROW_NUMBER() OVER (
  PARTITION BY department ORDER BY salary DESC
) = 1;

Não confunda HAVING com filtragem de janelas

Às vezes, os candidatos tentam usar HAVING para filtrar uma classificação. HAVING filtra grupos depois da agregação de GROUP BY e ainda é executado antes das funções de janela, portanto também não pode referenciar uma coluna de janela.

  • WHERE → filtra linhas antes do agrupamento e antes das janelas.
  • HAVING → filtra grupos agregados, ainda antes das janelas.
  • Para filtrar uma janela → é necessária uma consulta externa (ou QUALIFY).

Combinando um pré-filtro com um filtro de janela

Muitas vezes, você filtra tanto antes quanto depois da janela. Aplique os filtros comuns de linhas no WHERE interno, para que a janela veja apenas as linhas relevantes, e depois filtre o resultado da janela na consulta externa.

Neste exemplo, primeiro restringimos aos funcionários ativos e depois escolhemos, entre eles, o funcionário mais bem pago de cada departamento. Colocar WHERE active dentro altera as linhas que são classificadas.

WITH ranked AS (
  SELECT department, name, salary,
         ROW_NUMBER() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS rn
  FROM employees
  WHERE is_active = true        -- pre-filter before ranking
)
SELECT * FROM ranked
WHERE rn = 1;                   -- post-filter on the window

Observação sobre desempenho

Os entrevistadores podem perguntar se o encapsulamento prejudica o desempenho. Geralmente, não: o otimizador trata a subconsulta/CTE como parte de um único plano e calcula a janela uma única vez. Não há uma varredura adicional apenas porque você a encapsulou.

Uma ressalva: em alguns mecanismos, uma CTE pode funcionar como uma barreira de otimização (sendo materializada); portanto, em caminhos críticos, uma tabela derivada ou QUALIFY pode gerar um plano melhor. Analise com EXPLAIN se isso for importante.

Erros comuns

Lista de verificação final:

  • Nunca coloque uma função de janela em WHERE/HAVING — isso gera um erro.
  • Atribua sempre um nome alternativo à tabela derivada; uma subconsulta sem nome em FROM é rejeitada.
  • Escolha a função de classificação de acordo com o comportamento dos empates exigido pela pergunta.
  • Use QUALIFY somente onde houver suporte; caso contrário, use o encapsulamento com CTE/subconsulta.

Verificação rápida

Por que filtrar uma função de janela exige um encapsulamento?

Recapitulação: filtrando resultados de janela

Você concluiu o ciclo sobre as funções de janela de classificação:

  • As funções de janela são executadas depois de WHERE/GROUP BY/HAVING, portanto não é possível filtrá-las nesses pontos.
  • Encapsule a janela em uma subconsulta ou CTE (sempre com um nome alternativo) e filtre o resultado na consulta externa.
  • Isso viabiliza os N primeiros por grupo, a linha mais recente por chave e os limites de totais acumulados.
  • QUALIFY é um atalho prático, não padrão, disponível somente no Snowflake/BigQuery.

Agora você tem o conjunto completo de ferramentas de classificação mais cobrado pelos entrevistadores.

Perguntas Frequentes

A aula “Filtrando um resultado de janela” é grátis?

Sim — o texto completo de “Filtrando um resultado de janela” é 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 SQL Interview Prep, atualize para CoddyKit PRO. O curso de SQL Interview Prep inclui 4 aulas no total.

O que vou aprender em “Filtrando um resultado de janela”?

Entenda por que é necessário envolver uma função de janela em uma subconsulta ou CTE para filtrá-la. Você pratica SQL 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 SQL Interview Prep?

Nenhuma experiência prévia é necessária. SQL 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 “Filtrando um resultado de janela”?

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 SQL Interview Prep?

Sim. Cada aula de SQL 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. OVER, PARTITION BY e ORDER BY
  2. ROW_NUMBER para sequenciamento exclusivo
  3. RANK versus DENSE_RANK em empates
  4. Filtrando um resultado de janela
← Voltar para SQL Interview Prep