Até agora, exploramos a mecânica de diferentes tipos de junção. Nesta lição, iremos além do básico e veremos como aplicar as junções para resolver problemas de negócios comuns, lidar com múltiplas tabelas e combinar junções com agregação.
Em bancos de dados complexos, os dados de que você precisa estão frequentemente distribuídos em três ou mais tabelas conectadas por tabelas de junção (junction tables).
Cenário: Queremos ver uma lista de atores e os títulos dos filmes em que apareceram.
Isso requer três tabelas: actor, film_actor (a ponte) e film.
SELECT
a.first_name,
a.last_name,
f.title
FROM
actor AS a
INNER JOIN
film_actor AS fa ON a.actor_id = fa.actor_id
INNER JOIN
film AS f ON fa.film_id = f.film_id
ORDER BY
a.last_name
LIMIT 10;
Como funciona:
JOIN cria uma nova tabela virtual que o próximo JOIN pode usar.Um dos usos mais poderosos das junções é calcular estatísticas em tabelas relacionadas. Você pode usar funções como COUNT, SUM e AVG após a junção.
Cenário: Calcular o valor total gasto por cada cliente.
SELECT
c.first_name,
c.last_name,
SUM(p.amount) AS total_gasto
FROM
customer AS c
INNER JOIN
payment AS p ON c.customer_id = p.customer_id
GROUP BY
c.customer_id, c.first_name, c.last_name
ORDER BY
total_gasto DESC;
Nota: Ao usar GROUP BY com junções, sempre inclua a chave primária (customer_id) para garantir resultados únicos caso dois clientes tenham o mesmo nome.
Podemos usar o LEFT JOIN combinado com uma cláusula WHERE para encontrar registros que não possuem uma entrada correspondente em outra tabela.
Cenário: Encontrar todos os filmes que NÃO estão no nosso inventário no momento (significa que temos o registro, mas não temos cópias físicas).
SELECT
f.title
FROM
film AS f
LEFT JOIN
inventory AS i ON f.film_id = i.film_id
WHERE
i.inventory_id IS NULL;
Um erro comum é colocar um filtro na cláusula WHERE ao usar um LEFT JOIN, o que acidentalmente o transforma de volta em um INNER JOIN.
Incorreto:
-- Isso remove clientes sem pagamentos porque p.payment_date é verificado APÓS a junção
SELECT c.last_name, p.amount
FROM customer c
LEFT JOIN payment p ON c.customer_id = p.customer_id
WHERE p.payment_date > '2005-08-01';
Correto (mantendo todos os clientes):
-- Isso mantém todos os clientes, mas só une dados de pagamento que correspondam à data
SELECT c.last_name, p.amount
FROM customer c
LEFT JOIN payment p ON c.customer_id = p.customer_id
AND p.payment_date > '2005-08-01';
JOIN.JOIN com GROUP BY permite relatórios complexos entre entidades de negócios.LEFT JOIN ... WHERE ... IS NULL para encontrar lacunas em seus dados.ON vs. WHERE) ao trabalhar com junções externas.