CodeGym /Cursos /SQL SELF /Comparando WHERE e HAVING: explicação da ordem de execuçã...

Comparando WHERE e HAVING: explicação da ordem de execução e exemplos

SQL SELF
Nível 8 , Lição 2
Disponível

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:

  1. Primeiro executa o FROM, pegando as linhas da tabela.
  2. Depois entra o WHERE, filtrando só as linhas que batem com a condição.
  3. Depois disso, faz a agregação com GROUP BY. Você ganha uma nova tabela com os dados agrupados.
  4. Aplica o HAVING, filtrando os grupos que batem com a condição.
  5. 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:

  1. Na tabela students pega as linhas onde age > 18 (usando WHERE).
  2. As linhas que sobraram são agrupadas por department.
  3. Pra cada grupo, calcula a média de idade dos estudantes.
  4. Os grupos onde a média é menor ou igual a 20 são tirados com HAVING.
  5. 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:

  1. Primeiro tira as linhas onde age <= 18 (condição do WHERE).
  2. Agrupa os dados por departamento (GROUP BY department).
  3. Conta quantos estudantes tem em cada grupo.
  4. 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 :)

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION