Voltar para a lista de artigos Artigos
6 minutos de leitura

Qual é a Cláusula SQL HAVING?

Vocês estão aprendendo SQL? Você está se perguntando o que você pode usar o Cláusula HAVING para? Ou, talvez, você tenha tentado usar ONDE em seu GROUP BY agregados? Você está no lugar certo! Neste artigo, explicamos como usar TENDO com muitos exemplos.

Você já tentou filtrar suas métricas criadas com GROUP BY com uma cláusula WHERE e descobriu que não funcionava? Isto porque não é o que o WHERE faz. Você precisa de uma cláusula HAVING!

Neste artigo, vamos explicar como usar HAVING para filtrar seus dados agregados. Você aprenderá quando e como usá-los, sua sintaxe e a diferença do WHERE. Mostraremos estes em exemplos detalhados de uma empresa de aluguel de filmes.

Você está pronto? Vamos direto ao assunto!

O Dataset e o Problema

Neste artigo, nós usamos o film tabela do conjunto de dados da amostra Sakila. Ela contém uma lista de filmes que você pode alugar a partir de um serviço fictício de aluguel de DVDs.

Aqui está um exemplo de consulta e seu resultado.

SELECT
	title,
	release_year,
	language_id,
	rental_duration,
	length,
	rating
FROM
	film
LIMIT 10;
titlerelease_yearlanguage_idrental_durationlengthrating
ACADEMY DINOSAUR20061686PG
ACE GOLDFINGER20061348G
ADAPTATION HOLES20061750NC-17
AFFAIR PREJUDICE200615117G
AFRICAN EGG200616130G
AGENT TRUMAN200613169PG
AIRPLANE SIERRA20061662PG-13
AIRPORT POLLOCK20061654R
ALABAMA DEVIL200613114PG-13
ALADDIN CALENDAR20061663NC-17

Com estes dados, queremos ver que tipos de filmes as pessoas alugam por períodos mais curtos ou mais longos. Estas informações nos permitirão identificar o tipo de filmes e públicos em que podemos nos concentrar.

GROUP BY: Um resumo

Utilizamos HAVING em grupos criados com uma cláusula GROUP BY.

Vamos fazer um rápido lembrete de como agregamos dados com GROUP BY. Usamos GROUP BY para resumir nossos dados em métricas agregadas. Precisamos de duas coisas para isso:

  • Uma função de agregação como COUNT, MAX, ou AVG.
  • Uma coluna para agregar.

Por exemplo, queremos saber quantos filmes temos em cada categoria de classificação. Para responder a esta pergunta, usamos COUNT(*) para contar o número de filmes em cada grupo, e usamos GROUP BY para agregar esta métrica de acordo com os valores da coluna rating:

SELECT
	rating,
	COUNT(*) AS films
FROM
	film
GROUP BY rating
ORDER BY rating;
ratingfilms
G178
PG194
PG-13223
R195
NC-17210

O resultado mostra o número de filmes por classificação. A distribuição dos filmes por classificação é relativamente uniforme. A classificação mais popular é a PG-13, enquanto a menos popular é a G.

Para saber mais sobre GROUP BY, consulte este artigo detalhado ou esta lista de exemplos práticos.

Agora que revisamos o que é GROUP BY, podemos combiná-lo com HAVING!

Quando usar o HAVING SQL

O principal uso da operação HAVING é filtrar os dados agregados. Você pode usá-la ao resumir seus dados com GROUP BY em novas métricas, e você deseja selecionar os resultados com base nestes novos valores.

É semelhante ao WHERE, mas você os usa em circunstâncias diferentes. No final deste artigo, você vai ler mais sobre esta diferença em detalhes.

A Sintaxe SQL HAVING

Em termos de sintaxe, HAVING requer apenas uma linha após o GROUP BY. O seguinte trecho resume a sintaxe necessária para o uso de uma cláusula HAVING:

SELECT
	aggregate_function(column)
FROM
	table
GROUP BY column_to_aggregate_on
HAVING condition_on_aggregate_metric;

Esta sintaxe é concisa, mas vamos ver como ela funciona através de exemplos!

Exemplos de HAVING

Digamos que queremos saber que filmes as pessoas alugam por durações mais ou menos longas. Talvez estejamos interessados na duração do aluguel por classificação. Por exemplo, o foco em filmes com aluguéis mais curtos pode nos permitir ter uma rotatividade geral mais rápida. Vamos ver o que os dados podem nos dizer sobre esta questão!

Criamos duas métricas agregadas agrupadas por classificação. Depois, usamos HAVING para filtrar a tabela resultante sobre a duração média dos aluguéis (avg_rentdur).

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
GROUP BY rating
HAVING AVG(rental_duration) > 5

HAVING aqui selecionamos os dados com base em uma condição sobre um grupo que criamos com uma função agregada (AVG).

ratingfilmsAVG(rental_duration)AVG(length)
PG1945.0825112.0052
NC-172105.1429113.2286
PG-132235.0538120.4439

O resultado não inclui as classificações G e R, pois sua duração média de aluguel é inferior a 5 dias. As pessoas alugam filmes classificados PG, PG-13, ou NC-17 por períodos mais longos.

Interessante!

Já que estamos analisando categorias para suas durações de aluguel, vamos filtrar ainda mais nossos resultados. Também removeremos as classificações cuja duração média seja superior a duas horas. Fazemos isso adicionando outra condição de grupo à cláusula HAVING:

SELECT
	rating,
COUNT(*) AS films,
AVG(rental_duration),
AVG(length)
FROM
	film
GROUP BY rating
HAVING AVG(rental_duration) > 5
	AND AVG(length) < 120;

A condição adicional em AVG(length) filtra a classificação PG-13.

ratingfilmsAVG(rental_duration)AVG(length)
PG1945.0825112.0052
NC-172105.1429113.2286

Muito bem feito!

Você não pode usar WHERE para filtrar grupos

Mencionamos que HAVING é semelhante a WHERE, mas os utilizamos em diferentes cenários. Vejamos como isto se desenrola em nosso exemplo.

Vamos substituir HAVING por WHERE na consulta que acabamos de escrever:

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
GROUP BY rating
WHERE AVG(rental_duration) > 5

No entanto, isto resulta na seguinte mensagem de erro:

ERRO 1064 (42000): Você tem um erro em sua sintaxe SQL; verifique o manual que corresponde à sua versão do servidor MySQL para a sintaxe correta a ser usada perto de 'ONDE avg_rentdur > 5' na linha 9

Isto se deve ao fato de que GROUP BY cláusulas correm após WHERE cláusulas. Esta consulta tenta aplicar WHERE em avg_rentdur quando avg_rentdur ainda não existe!

Isto significa que podemos usar WHERE somente em dados "brutos" e não em valores agregados. Precisamos usar HAVING em métricas agregadas.

Usando tanto WHERE como HAVING em uma consulta

Vimos que usamos ONDE filtrar filas individuais e HAVING para filtrar em grupos. Para demonstrar ainda mais sua diferença, vamos ver um exemplo em que usamos tanto o HAVING quanto o WHERE!

Queremos saber como nossas descobertas anteriores mudam quando nos concentramos em filmes curtos. Para isso, limitamos a duração do filme a 60 minutos.

Em nossa consulta, fazemos isso aplicando WHERE na coluna de duração:

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
WHERE
	length < 60
GROUP BY rating
HAVING AVG(rental_duration) < 5;
ratingfilmsAVG(rental_duration)AVG(length)
G214.381053.0952
NC-17214.904851.3810
R114.636455.0000

Os resultados mostram que se nos concentramos apenas em curtas-metragens, encontramos vários filmes classificados NC-17 com aluguéis curtos em média. Esta descoberta pode nos dar idéias sobre o tipo de filmes que podemos introduzir em nossa futura seleção de ofertas.

Deseja saber mais sobre as diferenças entre HAVING e WHERE? Confira nosso artigo detalhado sobre o tema!

Saiba mais sobre o SQL HAVING!

Você gosta do que acabou de aprender? Certifique-se de não esquecer! Você aprende melhor SQL resolvendo problemas através de exemplos novos e desafiadores. Você pode configurar o mesmo ambiente de teste que nós usamos aqui, importar o mesmo conjunto de dados e reescrever as consultas que você acabou de aprender.

Entretanto, isso pode exigir muito trabalho, e você estaria apenas recriando os mesmos exemplos. Ao invés disso, recomendamos que você verifique nosso curso de prática! Ele o ajudará a praticar o SQL HAVING e outras cláusulas através de exemplos novos e desafiadores!

O que você acha? Você está pronto para isso?