Bora dar mais uma passada na ordem de execução das operações em SQL, e também sobre com o que WHERE e HAVING conseguem ou não conseguem trabalhar. Isso é um ponto importante, porque muita coisa em SQL depende disso. Você precisa sacar bem essa parada.
Então, qual é a diferença entre WHERE e HAVING, quando usar um, quando usar o outro, e como eles se conectam? Isso vai te ajudar a não se perder na lógica das queries e filtrar os dados de forma eficiente. Bora resumir o que já sabemos sobre WHERE e HAVING.
O que é WHERE?
WHERE é uma condição que serve pra filtrar linhas antes da agregação ou do uso de funções agregadas. Ou seja, primeiro você pega as linhas da tabela que batem com o critério, e só depois faz a agregação nelas.
👉 Imagina que você tá pegando frutas na feira. WHERE é tipo um filtro que te ajuda a tirar as maçãs ruins antes mesmo de começar a separar por tamanho ou cor.
Exemplo:
SELECT *
FROM students
WHERE age > 18;
Essa query vai pegar todos os estudantes com mais de 18 anos antes de fazer qualquer outra operação.
O que é HAVING?
HAVING é um filtro que é aplicado depois da agregação dos dados (GROUP BY). Ele serve pra colocar condições nas linhas já agrupadas, tipo deixar só os grupos onde a média das notas dos estudantes é maior que 80.
👉 Voltando pro exemplo das maçãs. HAVING é o filtro que você usa depois de já ter separado as maçãs nas cestas (grupos). Agora você quer, por exemplo, só as cestas (grupos) que têm mais de dez maçãs.
Exemplo:
SELECT cesta, COUNT(*)
FROM macas
GROUP BY cesta
HAVING COUNT(*) > 10;
Essa query vai pegar só as cestas onde tem mais de 10 maçãs.
Principais diferenças:
| Característica | WHERE |
HAVING |
|---|---|---|
| Aplicação | Filtra linhas antes da agregação | Filtra grupos depois da agregação |
| Trabalha com agregação | Não pode usar funções agregadas | Pode usar funções agregadas |
| Objetivo | Tira linhas desnecessárias pra agregação | Tira grupos que não batem com a condição |
Ordem de execução do WHERE, GROUP BY e HAVING
Pra entender melhor como WHERE e HAVING funcionam, bora ver a ordem de execução das queries SQL:
- Primeiro executa o
FROM, pegando as linhas da tabela. - Depois entra o
WHERE, filtrando só as linhas que batem com a condição. - Depois disso, faz a agregação com
GROUP BY. Você ganha uma nova tabela com os dados agrupados. - Aplica o
HAVING, filtrando os grupos que batem com a condição. - No final, pega os resultados do
SELECT.
Resumindo, fica assim:
1. FROM → 2. WHERE → 3. GROUP BY → 4. HAVING → 5. SELECT
Exemplo:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE age > 18
GROUP BY department
HAVING AVG(age) > 20;
Aqui rola o seguinte:
- Na tabela
studentspega as linhas ondeage > 18(usandoWHERE). - As linhas que sobraram são agrupadas por
department. - Pra cada grupo, calcula a média de idade dos estudantes.
- Os grupos onde a média é menor ou igual a 20 são tirados com
HAVING. - Mostra o resultado.
Exemplos de uso combinado
Exemplo 1: Filtrando antes e depois da agregação
Condição: achar departamentos onde tem mais de 5 estudantes, considerando só estudantes com mais de 18 anos.
Tabela original students
| id | name | department | age | gpa |
|---|---|---|---|---|
| 1 | Alex Lin | ComputerSci | 20 | 3.8 |
| 2 | Maria Chi | Math | 22 | 3.5 |
| 3 | Anna Song | ComputerSci | 19 | 4.0 |
| 4 | Otto Art | Math | 17 | 3.9 |
| 5 | Liam Park | Physics | 21 | 3.7 |
| 6 | Jane Doe | ComputerSci | 23 | 3.6 |
| 7 | Tom Brown | Math | 25 | 3.4 |
| 8 | Sara White | Math | 19 | 3.8 |
| 9 | John Smith | ComputerSci | 20 | 3.7 |
| 10 | Emily Green | Physics | 18 | 3.9 |
| 11 | Mark Blue | ComputerSci | 21 | 3.5 |
| 12 | Zoe Black | Math | 22 | 3.6 |
| 13 | Max Gray | ComputerSci | 20 | 3.9 |
| 14 | Eva Gold | Math | 23 | 3.7 |
| 15 | Nick Silver | Physics | 19 | 3.8 |
Query:
SELECT department, COUNT(*) AS student_count
FROM students
WHERE age > 18
GROUP BY department
HAVING COUNT(*) > 5;
Resultado: -- Resultado da query
| department | student_count |
|---|---|
| ComputerSci | 6 |
Explicação:
- Primeiro tira as linhas onde
age <= 18(condição doWHERE). - Agrupa os dados por departamento (
GROUP BY department). - Conta quantos estudantes tem em cada grupo.
- Tira os grupos onde tem 5 ou menos estudantes (
HAVING COUNT(*) > 5).
Exemplo 2: Erro ao usar WHERE no lugar do HAVING
Condição: Achar departamentos onde a média de idade é maior que 22 anos.
Query errada:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE AVG(age) > 22
GROUP BY department;
Erro: SQL não deixa usar funções agregadas tipo AVG no WHERE, porque nessa etapa os agregados ainda não foram calculados.
Query certa:
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 22;
Aqui a condição AVG(age) > 22 é aplicada depois da agregação.
Dicas práticas
Se você precisa filtrar linhas, usa WHERE. Exemplo: Achar todos os funcionários com salário maior que 5000.
SELECT *
FROM employees
WHERE salary > 5000;
Se você precisa filtrar grupos, usa HAVING. Exemplo: Achar departamentos com salário total maior que 100.000.
SELECT department, SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) > 100000;
Combina WHERE e HAVING pra condições mais complexas.
Exemplo: Achar países com população maior que 10 milhões, considerando só cidades com mais de 1 milhão de habitantes.
SELECT country, SUM(population) AS total_population
FROM cities
WHERE population > 1000000
GROUP BY country
HAVING SUM(population) > 10000000;
Erros comuns e como resolver
Um dos erros mais comuns é confundir WHERE com HAVING. Por exemplo, tentar usar função agregada no WHERE:
SELECT department, COUNT(*)
FROM students
WHERE COUNT(*) > 10
GROUP BY department;
Essa query vai dar erro, porque os cálculos agregados não estão disponíveis na etapa do WHERE. O jeito certo é usar HAVING:
SELECT department, COUNT(*)
FROM students
GROUP BY department
HAVING COUNT(*) > 10;
Outro erro é escolher a condição errada pro WHERE. Por exemplo:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE avg_age > 20
GROUP BY department;
Aqui a condição avg_age > 20 tá errada, porque avg_age ainda não foi calculado. O certo é jogar essa condição pro HAVING:
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 20;
Espero que agora você tenha entendido direitinho a diferença entre WHERE e HAVING, como usar cada um e como evitar os erros mais comuns. Isso vai te ajudar muito na hora de criar relatórios mais complexos, filtrar dados pra análise e otimizar suas queries. Ou seja, pra boa parte das queries SQL que você vai escrever :)
GO TO FULL VERSION