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 windowObservaçã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
QUALIFYsomente 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
- OVER, PARTITION BY e ORDER BY
- ROW_NUMBER para sequenciamento exclusivo
- RANK versus DENSE_RANK em empates
- Filtrando um resultado de janela