🎯 ATIVIDADE 07 — O PODER DA INFORMAÇÃO

📖 Fundamentação Teórica

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.

  1. Escreva uma consulta que conte quantos clientes existem cadastrados.
  2. Escreva uma consulta que mostre o preço do produto mais caro e do mais barato.
  3. 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.

  1. Liste o Nome do Cliente e a Data do Pedido de todos os pedidos realizados.
  2. 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):

  1. Formate suas consultas mantendo palavras-chave em maiúsculas (ex: SELECT, INNER JOIN, GROUP BY, HAVING).
  2. Salve todas as queries da Prática 1 e 2 em um único script .sql.
  3. Adicione comentários detalhados explicando a diferença prática entre LEFT JOIN e INNER JOIN e quando usar HAVING em vez de WHERE.
  4. Envie o arquivo (Atividade_07_SeuNome.sql) no Microsoft Teams.

💡 Checkpoint de Lógica

Importante

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 JOIN os 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.