📘 Semana 5 – Agrupamentos com GROUP BY e HAVING

📂 Tópico 1 - O que é GROUP BY?

A cláusula GROUP BY é uma ferramenta fundamental em SQL utilizada para **agrupar registros que possuem valores iguais em uma ou mais colunas**. Ela é especialmente útil quando queremos **resumir ou analisar dados por categorias**, facilitando a geração de relatórios e a tomada de decisões.

Por exemplo, imagine uma escola que deseja saber quantos alunos estão matriculados em cada curso. Com o GROUP BY, é possível agrupar os dados por curso e, em seguida, contar quantos alunos há em cada um.

💡 Aplicações no mundo real:
  • 📚 Uma escola pode agrupar alunos por cidade e calcular a média de idade em cada uma.
  • 🛒 Um supermercado pode agrupar vendas por produto para saber o total vendido de cada item.
  • 📊 Uma empresa pode agrupar funcionários por setor e calcular o salário médio em cada área.

Importância: O GROUP BY é frequentemente utilizado junto a funções agregadas como COUNT(), AVG(), SUM(), MIN() e MAX(), permitindo gerar análises por grupo em vez de sobre a tabela inteira.

📌 Sintaxe básica:

SELECT coluna_agrupada, funcao_agregada(coluna)
FROM nome_tabela
GROUP BY coluna_agrupada;
        
🎓 Exemplo prático:

Desejamos saber quantos alunos estão matriculados em cada curso.


SELECT curso, COUNT(*) AS total_alunos
FROM alunos
GROUP BY curso;
        

Neste exemplo, os registros da tabela alunos são agrupados pela coluna curso e a função COUNT(*) conta quantos alunos há em cada grupo.

🎯 Conclusão:

O GROUP BY é essencial para transformar dados brutos em informações úteis e organizadas por categoria. Ele é amplamente utilizado em relatórios escolares, sistemas de vendas, bancos de dados de empresas e qualquer situação onde agrupamentos são necessários para análise.

🧩 Tópico 2 - Exemplos práticos com GROUP BY e HAVING

O GROUP BY permite agrupar registros com base em uma ou mais colunas, sendo muito útil para criar resumos, contagens, médias, somas e outras análises. Já a cláusula HAVING é usada para aplicar condições após esses agrupamentos — ou seja, para filtrar os resultados agregados.

Diferente da cláusula WHERE, que filtra linhas antes da agregação, o HAVING é aplicado somente depois que os dados foram agrupados e processados pelas funções agregadas (COUNT, AVG, etc).

Imagine que você deseja encontrar apenas os cursos que possuem mais de 30 alunos. Como esse número só pode ser conhecido após contar os alunos por curso, o HAVING é a escolha certa para essa situação.

📌 Exemplo 1: Total de alunos por curso

Queremos saber quantos alunos existem em cada curso da escola:


SELECT curso, COUNT(*) AS total
FROM alunos
GROUP BY curso;
        
📌 Exemplo 2: Média de idade por curso

Vamos calcular a média de idade dos alunos em cada curso:


SELECT curso, AVG(idade) AS media_idade
FROM alunos
GROUP BY curso;
        
📌 Exemplo 3: Cursos com mais de 30 alunos

Agora queremos listar apenas os cursos que têm mais de 30 alunos. Aqui entra o HAVING:


SELECT curso, COUNT(*) AS total
FROM alunos
GROUP BY curso
HAVING COUNT(*) > 30;
        
🧠 Explicação mais clara:
  • WHERE → Filtra antes do agrupamento (ex: apenas alunos da cidade "Garanhuns").
  • HAVING → Filtra depois do agrupamento (ex: mostrar apenas cursos com mais de 30 alunos).
🌍 Aplicações no mundo real:
  • 📈 Relatórios de vendas com totais por mês, por cliente ou por produto.
  • 🧾 Filtragem de clientes com gastos acima da média em uma loja.
  • 🏫 Identificação de turmas com mais de 40 alunos para alertas pedagógicos.
  • 🚚 Análise de regiões com média de entregas acima de determinado valor.
💬 Dica:

Você pode combinar GROUP BY e HAVING com mais de uma coluna para gerar relatórios mais detalhados, como agrupamentos por cidade e curso ao mesmo tempo:


SELECT cidade, curso, COUNT(*) AS total
FROM alunos
GROUP BY cidade, curso
HAVING COUNT(*) > 5;
        
🧪 Tópico 3 - Exercícios práticos com GROUP BY e HAVING

A seguir, propomos exercícios práticos utilizando agrupamentos em SQL com GROUP BY e HAVING. Esses comandos são essenciais para criar relatórios e análises em sistemas escolares, empresariais e governamentais.

📘 Criação da tabela e inserção de dados

Use o seguinte script para criar a tabela alunos e preenchê-la com alguns registros:

CREATE TABLE alunos (
    id INTEGER PRIMARY KEY,
    nome TEXT,
    idade INTEGER,
    curso TEXT,
    turma TEXT,
    cidade TEXT
);

INSERT INTO alunos (id, nome, idade, curso, turma, cidade) VALUES
(1, 'Ana Clara', 17, 'Informática', 'A', 'Garanhuns'),
(2, 'Bruno Silva', 18, 'Logística', 'A', 'Caetés'),
(3, 'Carlos Eduardo', 19, 'Informática', 'B', 'Garanhuns'),
(4, 'Daniela Lima', 17, 'Logística', 'B', 'Capoeiras'),
(5, 'Eduarda Souza', 18, 'Informática', 'A', 'Garanhuns'),
(6, 'Felipe Costa', 16, 'Logística', 'C', 'Paranatama'),
(7, 'Gabriela Ramos', 17, 'Informática', 'C', 'Garanhuns'),
(8, 'Henrique Melo', 20, 'Logística', 'A', 'Caetés'),
(9, 'Isabela Nunes', 18, 'Informática', 'B', 'Correntes'),
(10, 'João Pedro', 17, 'Logística', 'C', 'Garanhuns');
📝 Propostas de exercícios
  1. Quantos alunos existem em cada turma?
    SELECT turma, COUNT(*) AS total_alunos FROM alunos GROUP BY turma;
  2. Qual a média de idade dos alunos por curso?
    SELECT curso, AVG(idade) AS media_idade FROM alunos GROUP BY curso;
  3. Liste apenas os cursos com mais de 4 alunos matriculados.
    SELECT curso, COUNT(*) AS total FROM alunos GROUP BY curso HAVING COUNT(*) > 4;
  4. Quantos alunos há por cidade de origem?
    SELECT cidade, COUNT(*) FROM alunos GROUP BY cidade;
  5. Liste os cursos que possuem média de idade inferior a 18 anos.
    SELECT curso, AVG(idade) FROM alunos GROUP BY curso HAVING AVG(idade) < 18;

Esses exercícios simulam cenários comuns na educação: relatórios por turma, análise por curso, estatísticas por cidade, entre outros. São extremamente úteis para quem deseja trabalhar com sistemas escolares, relatórios administrativos ou desenvolvimento de sistemas de gestão.

🏁 Tópico 4 - Desafio Final: Análise de Dados Educacionais

Agora que você já aprendeu a agrupar, filtrar e resumir dados usando GROUP BY e HAVING, é hora de aplicar esses conhecimentos em um desafio completo, simulando um cenário real de uma escola técnica.

📌 Contexto:

A coordenação pedagógica deseja entender melhor o perfil dos estudantes para tomar decisões sobre alocação de professores e turmas. Para isso, você precisa produzir relatórios com base na tabela alunos.

📊 Requisitos:
  1. Liste o número de alunos por curso, considerando apenas os que moram em Garanhuns:
    SELECT curso, COUNT(*) FROM alunos WHERE cidade = 'Garanhuns' GROUP BY curso;
  2. Liste apenas as turmas com mais de 2 alunos da cidade de Caetés:
    SELECT turma, COUNT(*) FROM alunos WHERE cidade = 'Caetés' GROUP BY turma HAVING COUNT(*) > 2;
  3. Calcule a média de idade dos alunos por cidade, mostrando apenas cidades com mais de 2 alunos:
    SELECT cidade, AVG(idade) FROM alunos GROUP BY cidade HAVING COUNT(*) > 2;
💡 Dica:

Use as funções COUNT() e AVG() junto ao GROUP BY para agrupar os dados corretamente. O HAVING permite aplicar filtros após o agrupamento — ou seja, sobre os dados já resumidos.

Esse tipo de análise é muito comum em relatórios gerenciais de escolas, empresas e órgãos públicos. Com o domínio desses recursos, você poderá extrair insights importantes diretamente do banco de dados.

Desafio extra: Monte uma consulta que liste os cursos onde a menor idade de aluno é inferior a 17 anos, agrupando os resultados.

SELECT curso, MIN(idade) AS menor_idade
    FROM alunos
    GROUP BY curso
    HAVING MIN(idade) < 17;
📝 Tópico 5 - Exercício Final: Relatório Gerencial

Neste exercício, você atuará como analista de dados de uma escola técnica e terá que gerar relatórios com base em uma base de dados de alunos, utilizando GROUP BY e HAVING.

📚 Cenário:

A direção da escola deseja obter informações estratégicas para tomar decisões sobre alocação de professores, divisão de turmas e desenvolvimento de projetos locais. Para isso, você deverá montar consultas SQL baseadas na tabela alunos.

📌 Tabela: alunos
  • id – identificador do aluno
  • nome – nome completo
  • idade – idade do aluno
  • cidade – cidade onde o aluno reside
  • curso – nome do curso (ex: Logística, Desenvolvimento de Sistemas)
  • turma – identificador da turma (ex: T1, T2, T3)
🎯 Tarefas:
  1. Liste o número total de alunos por curso.
  2. Exiba apenas os cursos que possuem mais de 4 alunos.
  3. Mostre a média de idade dos alunos agrupados por cidade.
  4. Exiba os cursos em que a média de idade dos alunos é superior a 18 anos.
  5. Liste as turmas com mais de 2 alunos que moram na cidade de Garanhuns.

Para resolver essas questões, você deverá utilizar corretamente as cláusulas GROUP BY e HAVING, e poderá combinar também com WHERE e funções agregadas como COUNT() e AVG().

💡 Dica: leia com atenção cada pergunta e pense em como filtrar os dados antes e depois do agrupamento.