Banco de Dados I — 2026.2

Aula 11
JOINs: Consultando Múltiplas Tabelas

👨‍🏫 Prof. Gustavo Pinto 🏛️ UFPA 📅 09 de junho de 2026 🕣 7h30 – 9h10

Agenda de hoje

Por Que Precisamos de JOIN?

Bancos de dados relacionais organizam dados em múltiplas tabelas para evitar redundância. JOIN é o mecanismo para reunir essas tabelas no momento da consulta.

Tabela: cliente

id_cliente, nome, email

Dados do comprador

Tabela: pedido

id_pedido, id_cliente, valor, data

id_cliente é FK → cliente

Pergunta

"Qual o nome do cliente que fez o pedido #42?"

A resposta está nas duas tabelas — precisamos de JOIN.

Produto Cartesiano — O Que Evitar

-- Sem JOIN: produto cartesiano (todas as combinações)
SELECT * FROM cliente, pedido;
-- Se cliente tem 100 linhas e pedido tem 500 → 50.000 linhas!

Produto cartesiano sem filtro é quase sempre um erro. Cada linha de uma tabela é combinada com cada linha da outra, gerando resultados sem sentido e potencialmente lentos.

A solução é sempre especificar a condição de junção — a coluna que relaciona as duas tabelas.

Old-Style JOIN

Junção Implícita — Como era antes do SQL-92

-- equijoin / theta join
SELECT c.nome, p.id_pedido
FROM   cliente c, pedido p
WHERE  c.id_cliente = p.id_cliente;

Tabelas listadas no FROM separadas por vírgula; condição de junção no WHERE.

Old-Style JOIN → INNER JOIN

Estilo antigo

SELECT c.nome, p.id_pedido
FROM   cliente c, pedido p
WHERE  c.id_cliente = p.id_cliente;

Estilo moderno (SQL-92)

SELECT c.nome, p.id_pedido
FROM   cliente c
INNER JOIN pedido p
  ON c.id_cliente = p.id_cliente;

Por baixo dos panos: o banco gera o produto cartesiano e filtra com o WHERE — semanticamente idêntico ao INNER JOIN, mas menos legível.

INNER JOIN — Apenas as Correspondências

INNER JOIN retorna apenas as linhas que têm correspondência em ambas as tabelas segundo a condição ON.

SELECT c.nome, p.id_pedido, p.valor
FROM   cliente c
INNER JOIN pedido p ON c.id_cliente = p.id_cliente;
-- Clientes sem nenhum pedido NÃO aparecem no resultado

A palavra INNER é opcional — JOIN sozinho já é INNER JOIN.

A cliente B pedido INNER JOIN apenas linhas com correspondência

INNER JOIN — Exemplo com Alias e Filtro

-- Alias de tabela (c, p) deixa o código mais limpo
SELECT
    c.nome          AS cliente,
    p.id_pedido,
    p.valor_total,
    p.status
FROM   cliente c
JOIN   pedido  p ON c.id_cliente = p.id_cliente
WHERE  p.status = 'entregue'
ORDER BY p.valor_total DESC
LIMIT  10;

Alias de tabela

Use letras curtas (c, p) para evitar repetir o nome completo. Prefixe colunas ambíguas com o alias.

WHERE após JOIN

Filtre normalmente com WHERE depois do JOIN. A condição ON é apenas para definir a junção.

LEFT JOIN — Todos da Tabela Esquerda

LEFT JOIN retorna todas as linhas da tabela à esquerda, mais as correspondências da direita. Onde não há correspondência, os campos da direita aparecem como NULL.

-- Todos os clientes, com ou sem pedido
SELECT    c.nome, p.id_pedido, p.valor_total
FROM      cliente c
LEFT JOIN pedido  p ON c.id_cliente = p.id_cliente;
-- Clientes sem pedido: id_pedido = NULL, valor_total = NULL

Caso de uso típico: "Quero ver todos os clientes — incluindo os que ainda não compraram nada."

A cliente B pedido LEFT JOIN todas as linhas da tabela esquerda (A)

RIGHT JOIN — Todos da Tabela Direita

RIGHT JOIN é o espelho do LEFT JOIN: retorna todas as linhas da tabela à direita, mais as correspondências da esquerda.

-- Todos os pedidos, mesmo sem cliente cadastrado
SELECT    c.nome, p.id_pedido, p.valor_total
FROM       cliente c
RIGHT JOIN pedido  p ON c.id_cliente = p.id_cliente;
-- Pedidos sem cliente: c.nome = NULL

Na prática

RIGHT JOIN é raro: qualquer RIGHT JOIN pode ser reescrito como LEFT JOIN trocando a ordem das tabelas.

Equivalência

A RIGHT JOIN B é idêntico a B LEFT JOIN A. Use LEFT JOIN por consistência.

A cliente B pedido RIGHT JOIN todas as linhas da tabela direita (B)

Comparativo: INNER × LEFT × RIGHT

INNER JOIN

Retorna somente as linhas com correspondência em ambas as tabelas.

Use quando quer apenas dados completos.

LEFT JOIN

Retorna todas da esquerda + correspondências da direita (NULL onde não há).

Use quando a tabela esquerda é a "principal".

RIGHT JOIN

Retorna todas da direita + correspondências da esquerda (NULL onde não há).

Equivalente a LEFT JOIN com tabelas invertidas.

-- Resumo rápido com a mesma base
SELECT c.nome, p.id_pedido FROM cliente c  JOIN       pedido p ON c.id = p.id_cliente; -- INNER
SELECT c.nome, p.id_pedido FROM cliente c  LEFT JOIN  pedido p ON c.id = p.id_cliente; -- LEFT
SELECT c.nome, p.id_pedido FROM cliente c  RIGHT JOIN pedido p ON c.id = p.id_cliente; -- RIGHT

Boas Práticas com JOIN

Esquerda vs Direita

A tabela esquerda é a que vem no FROM. A direita é a que vem após o JOIN.

FROM      cliente c   ← esquerda
LEFT JOIN pedido  p   ← direita

Como escolher? Pergunte: "De qual tabela não posso perder nenhuma linha?" Essa vai na esquerda. A outra, que pode não ter correspondência, vai na direita.

Sempre use alias

Prefixe colunas com o alias da tabela (c.nome, p.valor) para evitar ambiguidade e facilitar a leitura.

Condição ON vs WHERE

Coloque a condição de junção no ON, filtros de negócio no WHERE. Misturá-los no WHERE pode mudar a semântica de LEFT JOINs.

Verifique NULLs

Depois de um LEFT/RIGHT JOIN, colunas da tabela opcional podem ser NULL — trate isso nas queries e na aplicação.

Exercício

JOIN com GROUP BY e Agregação

Dado o esquema abaixo, escreva a query pedida.

cliente

id_cliente, nome, email

pedido

id_pedido, id_cliente, valor_total, status

Desafio

Escreva uma query que retorne o nome de cada cliente, o total de pedidos que ele fez e a receita total (soma de valor_total). Mostre apenas clientes com 3 ou mais pedidos, ordenado por receita decrescente.

Exercício

JOINs Encadeados — Mais de Duas Tabelas

Esquema com quatro tabelas relacionadas:

cliente → pedido

cliente.id_cliente = pedido.id_cliente

pedido → item_pedido

pedido.id_pedido = item_pedido.id_pedido

item_pedido → produto

item_pedido.id_produto = produto.id_produto

Dica

Siga as FKs do modelo ER — cada JOIN adiciona uma tabela ao caminho.

Desafio

Escreva uma query que liste o nome do cliente, o nome do produto, a quantidade e o preço unitário de todos os itens comprados por Ana Lima.

Exercício Reflexivo

Pensando criticamente sobre JOINs

Discuta com um colega. O objetivo é argumentar, não apenas responder.

Questão 1

Um sistema de biblioteca tem tabelas livro e emprestimo. Você quer listar todos os livros e, para cada um, mostrar quantas vezes foi emprestado (incluindo os nunca emprestados, com 0). Qual tipo de JOIN usar? Como a contagem deve ser feita para que livros nunca emprestados apareçam como 0 e não sejam excluídos?

Questão 2

Um colega escreveu: FROM pedido p LEFT JOIN cliente c ON … e outro escreveu FROM cliente c RIGHT JOIN pedido p ON …. As queries retornam o mesmo resultado? Em que situação uma pode ser preferível à outra?

Próxima Aula — 11/06 (Qui)

Laboratório de Consultas
Exercícios progressivos