Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🔗 CAPÍTULO 15: LÓGICA NULL, SUBQUERIES E JOINS

No mundo real corporativo, os dados nunca estão em uma única tabela. Eles estão espalhados por dezenas de tabelas normalizadas. O desenvolvedor sênior é aquele capaz de "costurar" essas informações em tempo real. 🛡️🧩


🎯 Objetivo Curricular

Dominar a lógica ternária do valor NULL, compreender o escopo de Subqueries e construir painéis complexos cruzando dados através de INNER, LEFT, RIGHT e FULL JOIN.


🏢 O Cenário Prático (Seu Desafio)

A equipe de faturamento da TecProExpress fez uma busca simples para somar todos os pacotes entregues, mas o valor bateu milhares de reais a menos do que o real. Por quê? Porque alguns pacotes ainda não tinham um Motorista designado (ID_Motorista = NULL), e o JOIN que o desenvolvedor júnior usou simplesmente deletou esses pacotes do relatório!

"Seu desafio é dominar as armadilhas do NULL e aplicar o tipo correto de JOIN para garantir que pacotes não atribuídos continuem aparecendo no faturamento geral."


🧠 Fundamentos: O Buraco Negro do NULL

No SQL, a lógica não é Binária (True/False). É Ternária (True/False/Unknown). O NULL representa o "Desconhecido". E a regra de ouro é: A matemática com o desconhecido sempre resulta em desconhecido.

  • 10 + NULL = NULL
  • 'A' = NULL -> FALSO (Nem o NULL é igual a outro NULL!)

🛠️ Como checar se algo é NULL?

Você não pode usar = (igual). Você deve usar a palavra IS.

-- Errado (Não retorna nada)
SELECT * FROM pacote WHERE id_motorista = NULL;

-- Certo (Traz os pacotes sem motorista)
SELECT * FROM pacote WHERE id_motorista IS NULL;

📖 Subqueries (A Consulta Inception)

Uma Subquery é um SELECT dentro de outro SELECT. Usamos isso quando precisamos do resultado de uma busca para poder fazer outra busca.

🛠️ Código do Exemplo (Quem ganha mais que a média?)

-- A Subquery (entre parênteses) roda PRIMEIRO e calcula a média. 
-- O valor calculado é passado para o SELECT de fora.
SELECT nome, salario 
FROM motorista 
WHERE salario > (SELECT AVG(salario) FROM motorista);

🔗 A Arte dos JOINs

Quando as tabelas foram normalizadas (Cap. 10), elas foram separadas. O JOIN é a "Supercola" que une elas de volta.

📊 Diagrama de Venn dos JOINs

flowchart LR
    subgraph INNER JOIN
    A1(("Tabela A")) --- B1(("Tabela B"))
    end
    
    subgraph LEFT JOIN
    A2((("Tabela A"))) --- B2(("Tabela B"))
    end
    
    style A1 fill:#e0e0e0
    style B1 fill:#e0e0e0
    style A2 fill:#4caf50
    style B2 fill:#e0e0e0

1. INNER JOIN (A Interseção Perfeita)

Retorna APENAS o que existe dos dois lados. (O erro do júnior da TecProExpress).

  • Se o pacote não tem motorista, ele não aparece.

2. LEFT JOIN (Preservando a Tabela da Esquerda)

Retorna TUDO da Tabela A (Esquerda), mesmo que ela não tenha correspondência na Tabela B. (A solução para o relatório!).

  • Todos os pacotes aparecem. Se não tiver motorista, a coluna do motorista vem preenchida com NULL.

🛠️ Prática Obrigatória: Salvando o Faturamento

Cenário: Corrigindo o erro do painel da TecProExpress.

  1. Crie a tabela motorista e a tabela pacote.
  2. Insira dois pacotes com motoristas e um pacote com id_motorista = NULL.
  3. Crie uma query que liste todos os pacotes, mostrando o nome do motorista apenas quando ele existir.

🚀 Script de Seed (Gabarito de JOINs)

-- DDL
CREATE TABLE motorista (id INT PRIMARY KEY, nome VARCHAR(50));
CREATE TABLE pacote (id INT PRIMARY KEY, descricao VARCHAR(50), valor DECIMAL(10,2), id_motorista INT);

-- DML
INSERT INTO motorista VALUES (1, 'Carlos'), (2, 'Ana');
INSERT INTO pacote VALUES (100, 'Geladeira', 200.00, 1);
INSERT INTO pacote VALUES (101, 'TV', 50.00, 2);
INSERT INTO pacote VALUES (102, 'Micro-ondas', 30.00, NULL); -- Pacote sem dono

-- O ERRO DO JÚNIOR (O Micro-ondas não aparece)
-- SELECT p.descricao, m.nome FROM pacote p INNER JOIN motorista m ON p.id_motorista = m.id;

-- DQL (A SOLUÇÃO COM LEFT JOIN)
SELECT p.descricao, p.valor, m.nome AS motorista_responsavel
FROM pacote p
LEFT JOIN motorista m ON p.id_motorista = m.id;

🔍 Detalhamento da Consulta:

  • pacote p: A letra p é um Alias (Apelido), para não precisarmos digitar o nome completo da tabela toda hora.
  • LEFT JOIN: O pacote é a Tabela A (Esquerda, citada antes do JOIN). Logo, a query promete: "Mostrarei todos os pacotes, custe o que custar!".

📤 Instruções de Entrega (Microsoft Teams)

Após validar seus códigos práticos e de estudo:

Use o operador e para critérios rigorosos e ou para critérios flexíveis. Salve os arquivos com a extensão .sql (Ex: Atividade_XX_SeuNome.sql ou Atividade_XX_SeuNome.png ou Atividade_XX_SeuNome.drawio


💡 Checkpoint de Lógica

[!IMPORTANT] Dica do Especialista: Você quer se destacar na engenharia de dados? Entenda que JOINs são operações matemáticas pesadas (Produto Cartesiano + Filtro). Em relatórios que cruzam 15 tabelas com milhões de linhas, a ordem que você escreve seus INNER JOIN e LEFT JOIN pode fazer a diferença entre a consulta terminar em 2 segundos ou travar o servidor da empresa. 🧠🛡️