having quer dizer tendo ou contendo em português e usamos HAVING para especificar uma condição e filtrar linhas geradas por group by.
Já group by quer dizer agrupar ou agrupar por.
A cláusula having fica imediatamente após a cláusula group by.
A Sintaxe é a seguinte:
select select_list from nome_tabela group by colune1, coluna2, ... having condicao_busca;
Para usar a cláusula having, você especifica uma condição de busca que pode consistir em uma ou mais expressões booleanas(true e false). A instrução select retornará apenas grupos (ou linhas) que fazem com que a condição de busca seja avaliada como verdadeira.
Tabelas que Usaremos nos Exemplos
Temos o banco de dados chamado nation que baixamos no artigo: MariaDB e MySQL: Baixando Exemplo de Banco de Dados
Usaremos as tabelas countries e regions.
Estrutura da tabela countries:
MariaDB [nation]> desc countries; +---------------+---------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+---------------+------+-----+---------+----------------+ | country_id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(50) | YES | | NULL | | | area | decimal(10,2) | NO | | NULL | | | national_day | date | YES | | NULL | | | country_code2 | char(2) | NO | UNI | NULL | | | country_code3 | char(3) | NO | UNI | NULL | | | region_id | int(11) | NO | MUL | NULL | | +---------------+---------------+------+-----+---------+----------------+
Estrutura da tabela regions:
MariaDB [nation]> desc regions; +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | region_id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(100) | NO | | NULL | | | continent_id | int(11) | NO | MUL | NULL | | +--------------+--------------+------+-----+---------+----------------+
Exemplos Usando GROUP BY e HAVING
#1 usando group by e having para encontrar regiões que tenham mais de 10 países
select regions.name, count(country_id) from countries inner join regions using(region_id) group by (regions.name) having count(region_id) > 10;
MariaDB [nation]> select regions.name, count(country_id) from countries inner join regions using(region_id) group by (regions.name) having count(region_id) > 10; +---------------------------+-------------------+ | name | count(country_id) | +---------------------------+-------------------+ | Caribbean | 24 | | Eastern Africa | 20 | | Middle East | 18 | | South America | 14 | | Southeast Asia | 11 | | Southern and Central Asia | 14 | | Southern Europe | 15 | | Western Africa | 17 | +---------------------------+-------------------+
#2 agora faremos o oposto, buscaremos regióes que tenham menos de 10 países
select regions.name, count(country_id) from countries inner join regions using(region_id) group by (regions.name) having count(region_id) < 10;
MariaDB [nation]> select regions.name, count(country_id) from countries inner join regions using(region_id) group by (regions.name) having count(region_id) < 10; +---------------------------+-------------------+ | name | count(country_id) | +---------------------------+-------------------+ | Antarctica | 5 | | Australia and New Zealand | 5 | | Baltic Countries | 3 | | British Islands | 2 | | Central Africa | 9 | | Central America | 8 | | Eastern Asia | 8 | | Melanesia | 5 | | Micronesia | 7 | | Micronesia/Caribbean | 1 | | Nordic Countries | 7 | | North America | 5 | | Northern Africa | 7 | | Southern Africa | 5 | | Western Europe | 9 | +---------------------------+-------------------+
#3 podemos usar um exemplo mais complexo. Abaixo usamos a cláusula having para encontrar regiões que tenham mais de 10 países e áreas totais maiores que 1.000.000 km2:
select regions.name, area, count(country_id) from countries inner join regions using(region_id) group by region_id having count(region_id) < 10 and area > 1000000;
MariaDB [nation]> select regions.name, area, count(country_id) from countries inner join regions using(region_id) group by region_id having count(region_id) < 10 and area > 1000000; +---------------------------+-------------+-------------------+ | name | area | count(country_id) | +---------------------------+-------------+-------------------+ | Central Africa | 1246700.00 | 9 | | Antarctica | 13120000.00 | 5 | | Australia and New Zealand | 7741220.00 | 5 | | Eastern Asia | 9572900.00 | 8 | | Northern Africa | 2381741.00 | 7 | +---------------------------+-------------+-------------------+