CodeGym /Cursos /SQL SELF /Filtrando dados agregados com HAVING

Filtrando dados agregados com HAVING

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

Olha só, ainda não falamos sobre como filtrar grupos depois de aplicar agregações? Às vezes, não queremos todos os cursos — só aqueles onde tem mais de cem estudantes. Ou queremos ver só os departamentos onde o salário médio passa de 50.000. Hoje vamos conhecer a filtragem de dados agregados usando o HAVING.

Pra que serve o HAVING, se já temos o WHERE? Não dava pra colocar o WHERE depois do GROUP BY? :)

Não é tão simples! Primeiro, a ordem dos operadores em SQL é fixa e o WHERE é executado antes do GROUP BY.

Será que dá pra colocar ele depois do GROUP BY?

Também não! Muitas vezes a gente precisa filtrar as linhas da tabela antes de agrupar. Depois agrupa os dados filtrados. E aí, depois da agregação, joga fora alguns dados que não interessam.

Então, será que não dava só copiar o operador WHERE, chamar de HAVING e colocar depois do GROUP BY?

É isso mesmo que rola! :)

Diferença entre HAVING e WHERE

WHERE filtra as linhas antes da agregação.

Pensa que você tá escolhendo bolos pelo sabor: morango e chocolate você deixa, o resto vai pro lado. Essa é a função do WHERE.

HAVING filtra depois que os dados já foram agrupados e as funções agregadas fizeram sua mágica.

Por exemplo, você já agrupou os bolos por mesa, contou quantos tem em cada uma e agora quer deixar só as mesas com mais de três bolos.

Então, HAVING serve pra filtrar dados no nível dos grupos.

Sintaxe do HAVING

A sintaxe é quase igual ao WHERE, mas funciona um pouco diferente:

SELECT colunas, funções_agregadas
FROM tabela
GROUP BY colunas
HAVING condição;

Etapas de execução:

  1. Primeiro as linhas são filtradas pelo WHERE.
  2. Depois os dados são agrupados com o GROUP BY.
  3. As funções agregadas são aplicadas nos resultados dos grupos.
  4. Por fim, o resultado é filtrado com o HAVING.

Exemplos de uso do HAVING

Exemplo 1: Filtrando cursos com muitos estudantes

Você quer saber quais cursos da faculdade têm mais de 100 estudantes. Suponha que temos a tabela students:

id name faculty
1 Alice Engineering
2 Bob Engineering
3 Charlie Arts
4 Daisy Business
5 ... ...

Consulta:

SELECT faculty, COUNT(*) AS student_count
FROM students
GROUP BY faculty
HAVING COUNT(*) > 100;

O que tá rolando aqui:

  • Primeiro a gente agrupa os estudantes pela coluna faculty usando o GROUP BY.
  • Depois a função agregada COUNT(*) conta quantos estudantes tem em cada curso.
  • Por fim, o HAVING elimina todos os cursos com 100 estudantes ou menos.

Resultado:

faculty student_count
Engineering 150
Arts 120

Exemplo 2: Departamentos com salário médio alto

Você quer achar só os departamentos onde o salário médio dos funcionários passa de 50.000. Suponha que temos a tabela employees:

id name department salary
1 Alice IT 60000
2 Bob HR 45000
3 Charlie IT 70000
4 Daisy HR 52000
5 ... ... ...

Consulta:

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;

Resultado:

department avg_salary
IT 65000

Repara: o HAVING trabalha com os resultados que foram calculados depois do GROUP BY.

Ordem de execução do WHERE, GROUP BY e HAVING

Filtrar com WHERE e HAVING acontece em etapas diferentes. Pra entender melhor a diferença, olha o passo a passo da consulta:

  1. WHERE: filtragem das linhas.

    Nessa etapa, todas as linhas da tabela são processadas. Se a linha não passa no WHERE, ela nem entra no resto do processo.

  2. GROUP BY: agrupamento das linhas.

    Depois de filtrar, as linhas são agrupadas pelos campos que você colocou no GROUP BY.

  3. Funções agregadas:

    As funções agregadas tipo COUNT(), AVG(), SUM() etc. são aplicadas nos grupos.

  4. HAVING: filtragem dos grupos.

    Nessa etapa, só os resultados das agregações são processados. As condições do HAVING só valem pros grupos.

Particularidades do HAVING

Particularidade 1: Trabalhando com agregados

A principal diferença do HAVING pro WHERE é que ele trabalha com funções agregadas. Por exemplo:

SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;

Nessa consulta, não dá pra usar AVG(salary) dentro do WHERE, porque o WHERE roda antes da agregação. Uma consulta tipo:

SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;

vai dar erro: aggregate functions are not allowed in WHERE.

Particularidade 2: Filtrando sem agrupar

Você pode usar o HAVING até sem um GROUP BY explícito. Nesse caso, a consulta é interpretada como se tivesse um grupo só — todos os registros:

SELECT AVG(salary) AS avg_salary
FROM employees
HAVING AVG(salary) > 50000;

Exemplo prático

Imagina que temos uma loja e uma tabela de vendas sales:

id product_id sales_amount
1 101 200.00
2 102 300.00
3 101 400.00
4 103 150.00

Consulta: achar produtos com volume total de vendas maior que 500.

SELECT product_id, SUM(sales_amount) AS total_sales
FROM sales
GROUP BY product_id
HAVING SUM(sales_amount) > 500;

Resultado:

product_id total_sales
101 600.00

Erros comuns

Usar agregados no WHERE:

Por exemplo:

SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;

Erro: não pode usar funções agregadas no WHERE.

Erros com NULL:

Se os dados têm NULL, a filtragem pode dar resultados estranhos. Por exemplo:

SELECT department, SUM(salary)
FROM employees
GROUP BY department
HAVING SUM(salary) > 0;

Se a coluna salary só tem NULL, o resultado pode ser zero ou vazio.

Parabéns! Agora você já consegue filtrar dados agregados de boa! Não esquece: HAVING é sua chave pra análise no nível dos grupos, onde o WHERE normal não dá conta.

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