SQL CROSS JOIN: Todas as Combinações de Linhas
Lição 5.6 · Tempo de leitura: ~5 min · Tarefas para praticar ↓
O SQL CROSS JOIN combina cada linha de uma tabela com cada linha de outra; o resultado chama-se produto cartesiano. Nesta lição, você vai aprender a sintaxe do CROSS JOIN, quão grande fica o resultado e como usá-lo para montar grades de relatório que mostram zeros em vez de linhas em falta.
Todas as junções vistas até agora emparelhavam linhas por uma condição. O CROSS JOIN não tem condição: cada linha da primeira tabela encontra cada linha da segunda. Raramente é isso que se quer com dados relacionados, mas é exatamente o necessário para gerar todas as combinações: cada loja com cada categoria, cada produto com cada tamanho, cada dia com cada funcionário.
O Que o CROSS JOIN Devolve
Se a primeira tabela tem m linhas e a segunda tem n linhas, o resultado tem m × n linhas. Não há cláusula ON.
Sintaxe Básica
SELECT table1.column1, table2.column2
FROM table1
CROSS JOIN table2;
A sintaxe antiga com vírgula, FROM table1, table2 sem condição, significa o mesmo. O CROSS JOIN deixa a intenção explícita e é a forma preferida.
Exemplo: Cada Loja com Cada Categoria
SELECT s.store_id, c.name AS category
FROM store AS s
CROSS JOIN category AS c
ORDER BY s.store_id, c.name;
Resultado: 32 linhas: 2 lojas × 16 categorias, cada loja com cada categoria.
Montar uma Grade de Relatório
O uso mais prático do CROSS JOIN é o "esqueleto" de um relatório. Suponha que você precise do número de filmes por loja e categoria, incluindo combinações com zero filmes. Uma junção normal com GROUP BY devolve apenas as combinações que existem nos dados. Um CROSS JOIN cria primeiro todas as combinações, e um LEFT JOIN depois anexa os dados:
SELECT s.store_id,
c.name AS category,
COUNT(i.inventory_id) AS copies
FROM store AS s
CROSS JOIN category AS c
LEFT JOIN film_category AS fc ON fc.category_id = c.category_id
LEFT JOIN inventory AS i ON i.film_id = fc.film_id
AND i.store_id = s.store_id
GROUP BY s.store_id, c.name
ORDER BY s.store_id, c.name;
Resultado: 32 linhas com o número de cópias de filmes de cada categoria em cada loja. Uma combinação sem cópias mostraria 0 em vez de desaparecer.
COUNT(i.inventory_id) conta apenas as cópias encontradas, por isso uma combinação sem cópias recebe 0. A mesma técnica preenche lacunas em séries temporais: um cross join entre uma lista de datas e uma lista de produtos dá uma linha para cada produto em cada dia.
O Produto Cartesiano Acidental
Um produto cartesiano aparece muitas vezes por engano, quando falta uma condição de junção:
-- Sem condição de junção: cada ator é combinado com cada filme
SELECT COUNT(*) AS row_count
FROM actor, film;
Resultado: 200 000 linhas: 200 atores × 1000 filmes.
Se uma consulta de repente devolve linhas demais, ou as linhas se repetem em combinações estranhas, verifique se cada tabela juntada tem uma condição de junção. Duas tabelas de 100 000 linhas cada produzem 10 bilhões de combinações, o que pode parar o banco de dados.
Principais conclusões:
- O
CROSS JOINcombina cada linha de uma tabela com cada linha de outra. - O resultado tem
m × nlinhas e não há condiçãoON. FROM a, bsem condição também é um produto cartesiano, muitas vezes acidental.CROSS JOINmaisLEFT JOINmonta uma grade de relatório completa, com zeros para combinações em falta.- Verifique o tamanho do resultado antes de fazer cross join de tabelas grandes.
Perguntas Frequentes
O que é um produto cartesiano em SQL?
O conjunto de todas as combinações de linhas de duas tabelas. Se uma tabela tem 2 linhas e a outra 16, o produto cartesiano tem 32 linhas. O CROSS JOIN devolve-o explicitamente.
Qual é a diferença entre CROSS JOIN e INNER JOIN?
O INNER JOIN mantém apenas as combinações que satisfazem a condição ON. O CROSS JOIN mantém todas as combinações. Um INNER JOIN com uma condição sempre verdadeira comporta-se como um CROSS JOIN.
Quando devo usar CROSS JOIN?
Quando você precisa de todas as combinações: grades de relatório, variantes de produtos (cores × tamanhos), calendários (datas × funcionários) ou para preencher lacunas em séries temporais junto com LEFT JOIN.