Voltar para a lista de artigos Artigos
5 minutos de leitura

HAVING vs. WHERE em SQL: O que você deve saber

Este artigo é sobre as cláusulas SQL's WHERE e HAVING. Ambas as cláusulas fazem parte dos fundamentos do comando SQL SELECT. Elas têm usos semelhantes, mas há também diferenças importantes que toda pessoa que usa SQL deve conhecer. Vamos ver o que está por trás do debate HAVING vs. WHERE.

Neste artigo, vamos supor que trabalhamos para uma agência social governamental que apóia pessoas ou famílias cuja renda está abaixo de um determinado limite. Esta agência usa várias métricas para identificar pessoas ou famílias que precisam de ajuda.

Primeiro, vejamos o conjunto de dados da amostra. Depois, no restante do artigo, criaremos consultas com base neste conjunto de dados.

Dataset de Amostra

Este conjunto de dados descreve pessoas pertencentes a quatro famílias que vivem em duas cidades. Por uma questão de simplicidade, assumiremos que last_name identifica a família. A idéia é obter métricas no nível da pessoa e no nível da família.

TABLE Persons

namelast_namebirth_dateyear_incomecity
MaryRoberts1964-01-1178000Oklahoma
PeterRoberts1962-09-2586500Oklahoma
JohnRoberts1999-06-030Oklahoma
SueRoberts1996-03-060Oklahoma
MelindaRoberts1998-04-040Oklahoma
GeorgeHudson1953-02-2348000Oklahoma
NancyHudson1958-12-0665000Oklahoma
AnnHudson1979-04-0235000Oklahoma
CarlGibson1963-04-03102800Phoenix
LiGibson1963-12-2796000Phoenix
KateBishop1994-07-10920000Phoenix
MarkBishop2018--9-130Phoenix

Está bem. Agora que já vimos o conjunto de dados, vamos começar!

ONDE e TENDO: Exemplos simples

Em palavras simples, as cláusulas WHERE e HAVING atuam como filtros; elas removem registros ou dados que não atendem a certos critérios do resultado final de uma consulta. Entretanto, elas são aplicadas a diferentes conjuntos de dados. Esse é o ponto importante para entender sobre WHERE vs. HAVING: WHERE filtra no nível de registro, enquanto HAVING filtra no nível de "grupo de registros ".

Vamos ver alguns exemplos.

Aqui está um exemplo de consulta que usa a cláusula WHERE: Suponha que queremos obter os nomes de pessoas com uma renda anual superior a 100.000 dólares. Precisamos filtrar (ou descartar) no nível de registro, então usaremos a cláusula WHERE em vez da cláusula HAVING para esta consulta:

Texto de consulta para fins de cópia-colar:

SELECT name, last_name
FROM  persons
WHERE year_income > 100000;

ONDE vs. HAVING

Agora vamos tentar uma consulta semelhante, mas desta vez com a cláusula HAVING: Suponha que queremos obter o last_name de famílias com renda familiar (ou seja, a renda somada de todos os membros da família) acima de 100.000 dólares. Este é um caso claro para usar a cláusula HAVING, pois não precisamos filtrar por registro. (Não vamos descartar o registro de uma pessoa porque ela ganha menos de 100.000 dólares). A idéia é filtrar com base na renda familiar, portanto precisamos agrupar as pessoas pelo site last_name e usar HAVING para filtrar os grupos de pessoas, como mostrado abaixo:

Texto de consulta para fins de copiar-colar:

SELECT 	last_name,
		SUM(year_income) AS "family_income"
FROM  persons
GROUP BY last_name
HAVING SUM(year_income) > 100000;

ONDE vs. HAVING

COMPLEXO COM CLÁUSULAS

Podemos utilizar quantas funções agregadas desejarmos na condição da cláusula HAVING. Vamos mais longe com nossa análise da renda familiar e calculamos a renda média por membro para cada família. Queremos identificar as famílias que ganham menos de 50.000 por pessoa. De um ponto de vista econômico, esta análise pode mostrar mais sobre os rendimentos familiares do que a anterior. Aqui está a pergunta:

Texto da consulta para fins de copiar-colar:

SELECT 	last_name, 
COUNT(*) as "members", 
SUM(year_income) as "family_income",
SUM(year_income) / COUNT(*) as "per_member_income"
FROM  persons
GROUP BY last_name
HAVING SUM(year_income)  / COUNT(*) < 50000;

ONDE vs. HAVING

Nota: A cláusula HAVING tem algumas restrições; uma delas é que as colunas de nível de registro na condição HAVING também devem aparecer na cláusula GROUP BY.

Usando WHERE e HAVING na mesma consulta SQL

É muito comum usar WHERE e HAVING na mesma consulta. Vamos fazer uma consulta para obter a renda familiar total e a renda por membro para as famílias em Oklahoma que têm mais de quatro membros:

Texto de consulta para fins de copiar-colar:

SELECT 	last_name, 
COUNT(*) as "members", 
SUM(year_income) as "family_income",
SUM(year_income) / COUNT(*) as "per_member_income"
FROM  persons
WHERE city = ‘Oklahoma’
GROUP BY last_name
HAVING COUNT(*) > 4;

ONDE vs. HAVING

ONDE e TENDO em Consultas Complexas

Para fechar o artigo, construiremos uma consulta que devolve famílias com uma renda familiar inferior à renda média de suas cidades. A parte complicada é a subconsulta que obtém a renda média de uma determinada cidade. Note que usamos uma consulta diferente porque esta é a renda média por cidade; não se baseia no número de membros por família, mas no número de famílias naquela cidade, conforme calculado com count(distinct last_name).

Texto de consulta para fins de copiar-colar:

SELECT
  last_name, 
  COUNT(*) AS "members", 
  SUM(year_income) AS "family_income",
  SUM(year_income) / COUNT(*) AS "per_member_income"
FROM persons p
GROUP BY last_name
HAVING SUM(year_income) < (
  SELECT 
  SUM(year_income) / COUNT(distinct last_name) 
  FROM persons 
  WHERE city = p.city
);
ONDE vs. HAVING

Solucionado: ONDE vs. HAVING em SQL

Revisamos várias consultas diferentes que utilizam as cláusulas WHERE e HAVING do SQL. Como mencionamos, ambas as cláusulas funcionam como filtros, mas cada uma se aplica a um nível de dados diferente. A cláusula WHERE filtra no nível de registro, enquanto a cláusula HAVING filtra no nível de grupo.

SQL é uma linguagem super flexível, e você pode criar milhões de combinações usando as cláusulas WHERE e HAVING. Neste ponto, eu gostaria de mencionar um grande curso relacionado aos tópicos deste artigo: LearnSQL's Como Criar Relatórios Básicos em SQL em SQL. Ele beneficia as pessoas que conhecem o básico de SQL e gostariam de melhorar suas habilidades na criação utilizando relatórios SQL significativos. Vá além - explore SQL!