HAVING versus WHERE
Compare a filtragem antes e depois do agrupamento e descubra qual cláusula enxerga a agregação.
HAVING versus WHERE é uma aula grátis de Coding Interview Prep no CoddyKit. Esta é a aula 2 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 Pergunta que Será Feita
“Qual é a diferença entre WHERE e HAVING?” é uma das perguntas mais frequentes em entrevistas de SQL. Uma resposta fraca diz: “HAVING é usado para agregados”. Uma resposta forte explica quando cada cláusula é executada no fluxo de execução da consulta.
Esse momento é o ponto central: WHERE filtra as linhas antes do agrupamento; HAVING filtra os grupos depois da agregação.
Onde Elas se Encaixam na Ordem de Execução
Relembre a ordem lógica de execução de uma consulta:
FROM/JOIN→ cria o conjunto de linhasWHERE→ filtra linhas individuaisGROUP BY→ transforma as linhas em gruposHAVING→ filtra os gruposSELECT→ projeta as colunasORDER BY→ ordena
WHERE acontece antes de os grupos existirem; HAVING acontece depois, por isso HAVING pode acessar agregados e WHERE não.
WHERE Não Pode Acessar Agregados
Como WHERE é executado antes do agrupamento, ele ainda não tem valores agregados. Escrever WHERE COUNT(*) > 5 causa um erro de sintaxe em qualquer banco de dados compatível com o padrão.
Entrevistadores inserem exatamente essa linha para verificar se você entende o fluxo de execução. O agregado ainda não existe quando WHERE é avaliado.
-- ERROR: aggregate not allowed in WHERE
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) > 5
GROUP BY department;HAVING Filtra os Grupos
Mova a condição do agregado para HAVING e ela funcionará, porque HAVING é executado depois que os grupos e seus agregados são calculados.
Interprete assim: “agrupe os funcionários e, depois, mantenha apenas os departamentos cuja contagem seja maior que cinco”.
SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;Coloque os Filtros de Linhas em WHERE
O erro inverso é filtrar linhas brutas em HAVING. Isso geralmente produz a resposta certa, mas é mais lento e enganoso, porque você agrupou linhas que pretendia descartar.
Regra prática: filtre por um valor de uma coluna bruta → WHERE. Filtre por um agregado → HAVING. Filtrar as linhas mais cedo reduz os dados que o agrupamento precisa processar.
-- Better: drop inactive rows BEFORE grouping
SELECT department, COUNT(*) AS headcount
FROM employees
WHERE status = 'active'
GROUP BY department
HAVING COUNT(*) > 5;As Duas Cláusulas Juntas
Uma consulta completa frequentemente usa ambas. WHERE restringe as linhas primeiro; HAVING então mantém os grupos que atendem aos critérios. Ler de cima para baixo corresponde à ordem lógica.
Exemplo resolvido: entre os pedidos feitos neste ano, encontre os clientes que gastaram mais de 1000 no total.
SELECT customer_id, SUM(amount) AS total_spent
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY customer_id
HAVING SUM(amount) > 1000;HAVING em Colunas Não Agregadas
HAVING pode fazer referência a uma coluna de agrupamento, não apenas a agregados. HAVING department = 'Sales' é válido, mas não faz sentido: esse filtro deve ficar em WHERE para ser executado mais cedo.
Se um entrevistador mostrar um HAVING que filtra uma coluna simples agrupada, a crítica esperada é: “mova-o para WHERE por eficiência”.
-- Works but inefficient; prefer WHERE department = 'Sales'
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING department = 'Sales';HAVING sem GROUP BY
Um caso sutil: HAVING é válido mesmo sem GROUP BY. A tabela inteira se torna um único grupo implícito, e HAVING filtra esse grupo.
Se a condição do agregado for falsa, você obterá zero linhas; se for verdadeira, uma linha. É raramente útil, mas entrevistadores perguntam sobre isso para confirmar que você entende o conceito de grupo implícito.
-- Returns the count only if the table has > 100 rows
SELECT COUNT(*) AS total
FROM orders
HAVING COUNT(*) > 100;HAVING Pode Usar um Alias de SELECT?
Assim como no caso do escopo de alias visto em outro contexto, os dialetos diferem. Postgres e MySQL permitem que HAVING faça referência a um alias de SELECT; SQL Server e Oracle não permitem.
O hábito portável é repetir a expressão do agregado em HAVING. Isso funciona em todos os mecanismos e evita surpresas em uma entrevista que envolva vários bancos de dados.
-- Portable: repeat the aggregate, do not rely on the alias
SELECT region, SUM(amount) AS total
FROM sales
GROUP BY region
HAVING SUM(amount) > 5000;Perspectiva de Desempenho
Para causar uma boa impressão, relacione as cláusulas ao desempenho: WHERE reduz as linhas que o mecanismo de agrupamento precisa examinar e pode usar índices; HAVING é executado sobre grupos já agregados, portanto não consegue reduzir o custo do agrupamento.
A conclusão que os entrevistadores esperam: aplique cada filtro o mais cedo possível. Somente condições que realmente dependem de um agregado precisam de HAVING.
A Resposta em Uma Frase
Memorize isto para a entrevista: “WHERE filtra as linhas antes do agrupamento e não pode acessar agregados; HAVING filtra os grupos depois da agregação e é a única cláusula que pode testar um valor agregado.”
Em seguida, apresente a lista da ordem de execução e você terá dado uma resposta completa e com tom de profissional experiente.
Verificação rápida
Decida a qual cláusula cada condição pertence.
Recapitulação
WHERE: filtra as linhas antes de GROUP BY; agregados não são permitidos. HAVING: filtra os grupos depois da agregação; é o único lugar onde uma condição de agregado é válida.
- Coloque os filtros de colunas brutas em WHERE para obter mais velocidade e usar índices.
- HAVING pode fazer referência a colunas agrupadas, mas não deve ser usado para filtros simples.
- HAVING funciona sem GROUP BY sobre o grupo implícito formado pela tabela inteira.
- Repita as expressões de agregados em HAVING para garantir compatibilidade entre dialetos.
Perguntas Frequentes
A aula “HAVING versus WHERE” é grátis?
Sim — o texto completo de “HAVING versus WHERE” é 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 “HAVING versus WHERE”?
Compare a filtragem antes e depois do agrupamento e descubra qual cláusula enxerga a agregação. 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 2 de 4.
Quanto tempo leva a aula “HAVING versus WHERE”?
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
- A regra de GROUP BY para colunas SELECT
- HAVING versus WHERE
- Agrupando por várias colunas e expressões
- Contando e filtrando grupos