O HAVING é uma cláusula SQL utilizada para filtrar resultados, assim como WHERE, com a diferença que ele suporta as funções de agregação.
Visão geral
A cláusula HAVING tem sido muito utilizada não só para filtrar resultados com funções de agregação, mas também para filtrar resultados após um agrupamento, o que não é permitido utilizando o WHERE. Outro ponto muito comum é a presença de subqueries como filtro.
Para os exemplos a seguir, considere a estrutura de tabelas abaixo, onde temos uma tabela chamada produto (Tabela 1), responsável por armazenar todos os produtos do estoque do cliente, a tabela categoria_produto (Tabela 2), responsável por armazenar todas as categorias existentes no banco de dados, e a tabela venda_produto (Tabela 3), que relaciona os produtos que foram vendidos.
id | nome | preco | Id_categoria |
1 | Bola | 35.00 | 1 |
2 | Patinete | 120.00 | 1 |
3 | Carrinho | 15.00 | 1 |
4 | Skate | 296.00 | 1 |
5 | Notebook | 3500.00 | 2 |
6 | Monitor LG 19 | 450.00 | 2 |
7 | O Diário de Anne Frank | 45.00 | 3 |
8 | O dia do Curinga | 65.00 | 3 |
9 | O mundo de Sofia | 48.00 | 3 |
10 | Através do Espelho | 38.00 | 3 |
id | nome |
1 | Infantil |
2 | Informatica |
3 | Educacional |
id | id_produto | valor | data |
1 | 1 | 35.00 | 2018-05-15 |
2 | 1 | 35.00 | 2018-06-15 |
3 | 1 | 35.00 | 2018-07-15 |
4 | 2 | 120.00 | 2018-07-15 |
5 | 2 | 120.00 | 2018-07-14 |
6 | 3 | 15.00 | 2018-07-15 |
7 | 7 | 45.00 | 2018-07-15 |
8 | 8 | 65.00 | 2018-07-15 |
9 | 8 | 65.00 | 2018-07-16 |
10 | 9 | 48.00 | 2018-07-16 |
11 | 5 | 3500.00 | 2018-07-16 |
12 | 5 | 3500.00 | 2018-07-16 |
13 | 6 | 450.00 | 2018-07-16 |
Sintaxe
SELECT
[ coluna1, coluna2, ... | * ]
FROM
[ tabela1, tabela2, ... ]
GROUP BY
[ campo1, campo2, ... ]
HAVING
[ condicao1, condicao2, ... ]
Na prática
Exemplo 1
Suponha que seja necessário listar todos os produtos que foram vendidos no ano de 2018 e que tiveram uma receita maior que 300. Para isso, podemos utilizar a query abaixo:
SELECT
P.nome,
SUM(V.valor) as RECEBIDO
FROM
produto P, venda_produto V
WHERE
YEAR(v.Data) = 2018 AND
P.id = V.id_produto
GROUP BY
P.id
HAVING
SUM(V.valor) > 300
No trecho de código acima, na linha 3 realizamos a soma da coluna valor da tabela venda_produto, nomeando a coluna no resultado de RECEBIDO.
Na linha 5 informamos que a consulta será realizada em duas tabelas, na tabela produto, nomeada de P, e na tabela venda_produto, nomeada de V.
Na linha 7 filtramos utilizando o WHERE o ano, definindo que somente resultados do ano de 2018 sejam trazidos pela consulta, e em seguida, na linha 8 realizamos o vínculo entre as duas tabelas, definindo que o ID da tabela produto seja o mesmo na tabela venda_produto.
Nas linhas 9 e 10 agrupamos o resultado do produto, para que venha apenas uma ocorrência de cada.
Nas linhas 11 e 12 utilizamos o HAVING para filtrar os depois do agrupamento, definindo que serão trazidos somente resultados que a soma da coluna valor seja maior que 300.
No exemplo acima, utilizamos no HAVING a função SUM, para filtrar com base no resultado de uma soma, o que não é possível fazer utilizando a cláusula WHERE.
O resultado pode ser visto na Tabela 4.
Nome | RECEBIDO |
Notebook | 7000.00 |
Monitor LG 19 | 450.00 |
Exemplo 2
Como outro exemplo, podemos aproveitar a mesma estrutura de tabelas para realizar outra consulta. Suponha que seja necessário trazer todos os produtos cadastrados e a sua receita total gerada, mas exibir no resultado somente os produtos que tiverem no mínimo duas vendas. Para isso, podemos utilizar a query abaixo:
SELECT
P.id,
P.nome as PRODUTO,
SUM(V.valor) as RECEITA
FROM
produto P,
venda_produto V
WHERE
P.id = V.id_produto
GROUP BY
P.id
HAVING
COUNT(V.id_produto) >= 2
No trecho de código acima, na linha 4 solicitamos a soma dos valores da coluna valor da tabela venda_produto, e em seguida, nas linhas 5 a 7 informamos que a consulta será realizada em duas tabelas, na tabela produto, nomeada de P, e na tabela venda_produto, nomeada de V.
Na linha 9 informamos que o id da tabela produto será o mesmo da tabela venda_produto, realizando assim o vínculo entre as duas.
Nas linhas 10 e 11 agrupamos o resultado da consulta pelo id do produto, afinal, precisamos apenas de uma ocorrência e seu valor total de receita;
Nas linhas 12 e 13 utilizamos o HAVING para filtrar o resultado, exibindo somente os resultados que tenham no mínimo duas vendas, utilizando a função COUNT para isso.
O resultado pode ser visto na Tabela 5.
id | PRODUTO | RECEITA |
1 | Bola | 105.00 |
2 | Patinete | 240.00 |
5 | Notebook | 7000.00 |
8 | O dia do Curinga | 130.00 |
Exemplo 3
Para este exemplo, considere a tabela abaixo, a tabela pessoa (Tabela 6), responsável por manter as informações de todas as pessoas do banco de dados:
id | Nome | |
1 | Pedro Henrique | pedro@gmail.com |
2 | Thiago Henrique | thiago@gmail.com |
3 | Thiago Henrique | thiago@gmail.com |
4 | Thiago Henrique | thiago@gmail.com |
5 | Gabriel Felipe | gabriel@gmail.com |
6 | Pedro Henrique | pedrohenrique@gmail.com |
Suponha que seja necessário trazer todas as pessoas que tenham o nome igual ao nome de outra pessoa no banco de dados, ou seja, trazer apenas homônimos. Para isso podemos utilizar a query abaixo:
SELECT
nome
FROM
pessoa
GROUP BY
nome
HAVING
COUNT(nome) > 1
No trecho de código acima, nas Linhas 1 a 6 trazemos todas as pessoas do banco de dados, e agrupamos por nome. O diferencial acontece na Linha 7 e 8, onde utilizamos a cláusula HAVING para trazer no resultado, somente os nomes que tenham aparecido no resultado mais de uma vez.
O resultado da query pode ser visto abaixo:
Nome |
Pedro Henrique |
Thiago Henrique |