Joins — Juntando Tabelas
Aula 2 de 8
Relacionamentos
-- Tabelas para os exemplos
CREATE TABLE clientes (
id SERIAL PRIMARY KEY,
nome VARCHAR(100) NOT NULL
);
CREATE TABLE pedidos (
id SERIAL PRIMARY KEY,
cliente_id INTEGER REFERENCES clientes(id),
total DECIMAL(10,2) NOT NULL,
data_pedido DATE DEFAULT CURRENT_DATE
);
INSERT INTO clientes VALUES
(1, 'João'), (2, 'Maria'), (3, 'Carlos'), (4, 'Ana');
INSERT INTO pedidos VALUES
(1, 1, 100.00, '2024-01-15'),
(2, 1, 250.00, '2024-02-10'),
(3, 2, 150.00, '2024-01-20'),
(5, 5, 50.00, '2024-03-01'); -- cliente_id 5 não existe!
INNER JOIN
-- Apenas registros que existem em ambas as tabelas
SELECT c.nome, p.id AS pedido_id, p.total
FROM clientes c
INNER JOIN pedidos p ON p.cliente_id = c.id;
-- Resultado: João (2x), Maria (1x). Carlos e Ana não aparecem (sem pedidos)
-- Pedido 5 não aparece (cliente_id 5 não existe em clientes)
LEFT JOIN
-- Todos da esquerda + correspondências da direita
SELECT c.nome, p.id AS pedido_id, COALESCE(p.total, 0) AS total
FROM clientes c
LEFT JOIN pedidos p ON p.cliente_id = c.id;
-- Resultado: João (2x), Maria (1x), Carlos (NULL), Ana (NULL)
RIGHT JOIN
-- Todos da direita + correspondências da esquerda
SELECT c.nome, p.id AS pedido_id
FROM clientes c
RIGHT JOIN pedidos p ON p.cliente_id = c.id;
-- Resultado: João (2x), Maria (1x), NULL (pedido 5 sem cliente)
FULL JOIN
-- Todos de ambas as tabelas
SELECT c.nome, p.id AS pedido_id
FROM clientes c
FULL JOIN pedidos p ON p.cliente_id = c.id;
-- Resultado: João, Maria, Carlos, Ana + pedido 5 (sem cliente)
CROSS JOIN
-- Produto cartesiano (cada linha A × cada linha B)
SELECT c.nome, p.id AS pedido_id
FROM clientes c
CROSS JOIN pedidos p;
-- 4 clientes × 4 pedidos = 16 linhas
Self Join
CREATE TABLE funcionarios (
id SERIAL PRIMARY KEY,
nome VARCHAR(100),
gerente_id INTEGER REFERENCES funcionarios(id)
);
INSERT INTO funcionarios VALUES
(1, 'Diretor', NULL),
(2, 'Gerente', 1),
(3, 'Dev Senior', 2),
(4, 'Dev Junior', 3);
SELECT f.nome AS funcionario, g.nome AS gerente
FROM funcionarios f
LEFT JOIN funcionarios g ON f.gerente_id = g.id;
Lab: Consulta Relacional
-- Vendas por cliente com total gasto
SELECT
c.id,
c.nome,
COUNT(p.id) AS total_pedidos,
COALESCE(SUM(p.total), 0) AS total_gasto,
COALESCE(AVG(p.total), 0) AS ticket_medio
FROM clientes c
LEFT JOIN pedidos p ON p.cliente_id = c.id
GROUP BY c.id, c.nome
ORDER BY total_gasto DESC;
-- Clientes sem pedidos
SELECT c.nome
FROM clientes c
LEFT JOIN pedidos p ON p.cliente_id = c.id
WHERE p.id IS NULL;
-- Produtos mais vendidos (3 tabelas)
SELECT
pr.nome,
SUM(iv.quantidade) AS total_vendido
FROM produtos pr
JOIN itens_venda iv ON iv.produto_id = pr.id
JOIN vendas v ON v.id = iv.venda_id
WHERE v.data BETWEEN '2024-01-01' AND '2024-12-31'
GROUP BY pr.nome
ORDER BY total_vendido DESC
LIMIT 10;
INNER JOIN = só correspondências. LEFT JOIN = todos da esquerda. Self join = tabela consigo mesma (hierarquias). LEFT JOIN + WHERE NULL = anti-join (registros sem correspondência).