🎯 ATIVIDADE 07 — O PODER DA INFORMAÇÃO
Para realizar este laboratório com sucesso, certifique-se de ter compreendido os conceitos apresentados no:
👉 CAPÍTULO 07: CHAVES, RELACIONAMENTOS E CARDINALIDADE
Bem-vindo à sétima semana (4 aulas) do curso de Banco de Dados. Agora que você já sabe inserir dados e fazer filtros básicos, vamos aprender o que realmente torna um Analista de Dados valioso: a capacidade de cruzar informações de tabelas diferentes e realizar cálculos automáticos. 🛡️🧩
🎯 Objetivos de Aprendizagem do Laboratório
Ao final deste laboratório prático (estimativa: 4 horas presenciais / autoguiadas), você será capaz de:
- Realizar junções entre tabelas usando
INNER JOIN. - Utilizar funções de agregação (COUNT, SUM, AVG, MAX, MIN).
- Agrupar resultados com
GROUP BY. - Filtrar grupos com
HAVING.
🏢 O Cenário Prático (Seu Desafio)
O Diretor Financeiro da TecProExpress precisa de um relatório consolidado. Ele não quer ver apenas "quem comprou", ele quer saber o Total Gasto por Cliente e quais são os Produtos mais vendidos.
Para isso, você precisará conectar as tabelas CLIENTE, PEDIDO e ITEM_PEDIDO, realizando somas e contagens automáticas.
🧠 Fundamentos: A Teoria Traduzida
Dados isolados são apenas registros. Dados cruzados são Inteligência de Negócio.
1. O Aperto de Mão (INNER JOIN)
Imagine que a tabela CLIENTE tem o nome e a tabela PEDIDO tem a data. O JOIN é o ponto de encontro onde o id_cliente de ambas as tabelas se reconhece.
graph LR
A["CLIENTE (ID: 1, Nome: Ana)"] -- "id_cliente = id_cliente" --- B["PEDIDO (ID: 101, Data: 12/05)"]
style A fill:#e3f2fd
style B fill:#fffde7
2. A Calculadora do Banco (Agregações)
Em vez de somar na mão, o banco faz por você:
- COUNT: Conta quantas linhas existem.
- SUM: Soma valores numéricos.
- AVG: Calcula a média.
📖 Exemplo Guiado: Relatório de Vendas
Veja como unir tabelas e somar valores em um único comando.
1. Preparando o Ambiente (DDL e Seed)
-- Estrutura Simplificada
CREATE TABLE categoria (id INT PRIMARY KEY, nome VARCHAR(50));
CREATE TABLE produto (id INT PRIMARY KEY, nome VARCHAR(50), preco DECIMAL(10,2), cat_id INT);
-- Seed
INSERT INTO categoria VALUES (1, 'Eletrônicos'), (2, 'Acessórios');
INSERT INTO produto VALUES (1, 'Mouse', 50.00, 2), (2, 'Teclado', 150.00, 2), (3, 'Monitor', 900.00, 1);
2. A Consulta com JOIN e SUM
-- Qual o valor total em estoque por categoria?
SELECT c.nome, SUM(p.preco) AS total_estoque
FROM categoria c
INNER JOIN produto p ON c.id = p.cat_id
GROUP BY c.nome;
🔍 Detalhamento do Código:
- INNER JOIN ... ON: Diz ao banco: "Traga apenas os produtos que possuem uma categoria válida".
- SUM(p.preco): Soma os preços de todos os produtos que caírem no mesmo grupo.
- GROUP BY: Organiza os resultados em "gavetas" pelo nome da categoria.
🛠️ Prática Obrigatória 1: Agregando Valores
Cenário: Análise de inventário da TecProExpress.
- Escreva uma consulta que conte quantos clientes existem cadastrados.
- Escreva uma consulta que mostre o preço do produto mais caro e do mais barato.
- Calcule a média de preços de todos os produtos.
🏁 Resultado Esperado (Seed Visual)
O resultado deve ser um valor único (ex: "Média: 450.50").
🛠️ Prática Obrigatória 2: O Grande Relatório (Join)
Cenário: Cruzamento de Pedidos e Clientes.
- Liste o Nome do Cliente e a Data do Pedido de todos os pedidos realizados.
- Desafio de Agrupamento: Mostre o nome do cliente e quantos pedidos cada um realizou até agora.
🚀 Script de Seed para Teste (SQL)
-- Use as tabelas da Atividade 06 e adicione estes dados:
INSERT INTO pedido (data_ped, id_cliente) VALUES
('2026-05-01', 1),
('2026-05-02', 1),
('2026-05-03', 2);
💻 Execução de Consulta Agrupada (JOIN + GROUP BY) no Terminal
Para testar o relatório de total de pedidos agrupados por cliente:
-- Query de agregação com JOIN e GROUP BY
SELECT c.nome, COUNT(p.id) AS total_pedidos
FROM cliente c
INNER JOIN pedido p ON c.id = p.id_cliente
GROUP BY c.nome
HAVING COUNT(p.id) >= 1;
🖥️ Saída Esperada no Terminal:
nome | total_pedidos
--------------+---------------
Marcos Silva | 2
Julia Costa | 1
(2 rows)
🌐 Requisição cURL para Relatório Agregado (Swagger /docs)
curl -X GET "http://127.0.0.1:8000/api/v1/relatorios/pedidos-por-cliente" \
-H "Accept: application/json"
🔹 Resposta JSON:
[
{
"cliente": "Marcos Silva",
"total_pedidos": 2,
"valor_acumulado": 745.00
},
{
"cliente": "Julia Costa",
"total_pedidos": 1,
"valor_acumulado": 150.00
}
]
📤 Instruções de Entrega (Microsoft Teams)
Após testar suas consultas agrupadas e junções no pgAdmin (ou SGBD de sua escolha):
- Formate suas consultas mantendo palavras-chave em maiúsculas (ex:
SELECT,INNER JOIN,GROUP BY,HAVING). - Salve todas as queries da Prática 1 e 2 em um único script
.sql. - Adicione comentários detalhados explicando a diferença prática entre
LEFT JOINeINNER JOINe quando usarHAVINGem vez deWHERE. - Envie o arquivo (
Atividade_07_SeuNome.sql) no Microsoft Teams.
💡 Checkpoint de Lógica
Reflexão Profissional:
Qual a diferença entre WHERE e HAVING? O WHERE filtra linhas antes do agrupamento. O HAVING filtra o resultado depois que o cálculo (como o SUM) já foi feito. 🧠🛡️
🔥 Desafio de Fixação (Opcional)
Nível: Arquiteto de BI 🏆
Crie um relatório que mostre apenas os clientes que gastaram mais de R$ 1.000,00 no total de suas compras. Você precisará usar JOIN, SUM, GROUP BY e HAVING.
🔑 Gabarito de Código/Fórmulas Completo
Prática 1 (Agregações):
SELECT COUNT(*) FROM cliente;
SELECT MAX(preco), MIN(preco) FROM produto;
SELECT AVG(preco) FROM produto;
Prática 2 (Joins):
-- Nome do Cliente e Data
SELECT c.nome, p.data_ped
FROM cliente c
INNER JOIN pedido p ON c.id = p.id_cliente;
-- Contagem por Cliente
SELECT c.nome, COUNT(p.id) AS total_pedidos
FROM cliente c
LEFT JOIN pedido p ON c.id = p.id_cliente
GROUP BY c.nome;
🔍 Explicação do Gabarito:
- LEFT JOIN: Usei aqui para que mesmo clientes que ainda não compraram nada apareçam na lista com o valor 0. O
INNER JOINos excluiria. - AS total_pedidos: Renomeia a coluna no resultado para ficar mais legível para o usuário final.
📊 Rubrica Formativa de Avaliação
| Critério de Avaliação | Insuficiente (0% - 40%) | Regular (41% - 70%) | Excelente (71% - 100%) |
|---|---|---|---|
| Junções de Tabelas (INNER JOIN vs LEFT JOIN) | Erros de sintaxe nas cláusulas `ON` de junção ou confunde os tipos de JOIN. | Escreve `INNER JOIN` mas não consegue aplicar `LEFT JOIN` para registros nulos. | Aplica `INNER JOIN` e `LEFT JOIN` com maestria, justificando a inclusão de registros nulos. |
| Funções de Agregação & Agrupamento | Erro de execução por omitir colunas no `GROUP BY` ou usar `WHERE` em vez de `HAVING`. | Utiliza `COUNT`/`SUM` com `GROUP BY` mas sem aplicar filtros `HAVING`. | Queries complexas impecáveis utilizando `COUNT`, `SUM`, `AVG`, `GROUP BY` e `HAVING`. |
| Entrega do Script SQL | Entrega script com palavras-chave em minúsculo ou sem formatação. | Script entregue mas sem explicações nos comentários. | Submete `Atividade_07_SeuNome.sql` perfeitamente formatado e com comentários explicativos. |