CROSS JOIN

El CROSS JOIN es fundamentalmente diferente a los otros tipos de JOIN. No necesita una condición de unión porque su propósito es generar el producto cartesiano de dos tablas: combina cada fila de la primera tabla con cada fila de la segunda. Si la primera tabla tiene 10 filas y la segunda tiene 5, el resultado tendrá 50 filas (10 × 5).

A primera vista puede parecer inútil o incluso peligroso (puede generar resultados enormes), pero tiene casos de uso muy específicos donde es exactamente la herramienta correcta.

Sintaxis

-- Sintaxis explícita
SELECT columnas
FROM tabla1
CROSS JOIN tabla2;
 
-- Sintaxis implícita (equivalente)
SELECT columnas
FROM tabla1, tabla2;

Ambas formas producen el mismo resultado. No hay cláusula ON porque no existe una condición de relación: se generan todas las combinaciones posibles. Si añades un WHERE, el resultado se filtra después de generar el producto cartesiano.

Producto cartesiano

Para visualizar lo que hace un CROSS JOIN, combinemos los 3 vendedores con los 5 estados posibles de un pedido:

SELECT
    e.nombre AS empleado,
    p.estado
FROM empleados e
CROSS JOIN (SELECT DISTINCT estado FROM pedidos) AS p
WHERE e.puesto LIKE '%Vendedor%' OR e.puesto LIKE '%Vendedora%'
ORDER BY e.nombre, p.estado;
empleadoestado
Danielcancelado
Danielentregado
Danielenviado
Danielpendiente
Danielprocesando
Nataliacancelado
Nataliaentregado
Nataliaenviado
Nataliapendiente
Nataliaprocesando
Patriciacancelado
Patriciaentregado
Patriciaenviado
Patriciapendiente
Patriciaprocesando
Raúlcancelado
Raúlentregado
Raúlenviado
Raúlpendiente
Raúlprocesando

Cada empleado de ventas se combina con cada estado posible, generando 4 × 5 = 20 filas. Todavía no es útil por sí solo, pero es el primer paso para construir informes completos donde necesitas que aparezcan todas las combinaciones, incluso las que no tienen datos.

Generar una matriz completa con LEFT JOIN

El caso de uso más práctico del CROSS JOIN es combinarlo con un LEFT JOIN para crear una matriz que incluya los ceros. Si quisieras ver cuántos pedidos ha gestionado cada vendedor en cada estado, incluyendo las combinaciones que no han ocurrido:

SELECT
    e.nombre AS empleado,
    estados.estado,
    COUNT(p.id) AS pedidos
FROM empleados e
CROSS JOIN (SELECT DISTINCT estado FROM pedidos) AS estados
LEFT JOIN pedidos p ON e.id = p.empleado_id
    AND p.estado = estados.estado
WHERE e.id IN (4, 5, 6)
GROUP BY e.nombre, estados.estado
ORDER BY e.nombre, estados.estado;
empleadoestadopedidos
Danielcancelado1
Danielentregado3
Danielenviado1
Danielpendiente2
Danielprocesando1
Nataliacancelado1
Nataliaentregado3
Nataliaenviado2
Nataliapendiente3
Nataliaprocesando1
Patriciacancelado1
Patriciaentregado1
Patriciaenviado1
Patriciapendiente2
Patriciaprocesando2

El CROSS JOIN genera todas las combinaciones empleado-estado (15 filas para 3 empleados × 5 estados). El LEFT JOIN con pedidos rellena los conteos reales. Si algún empleado no tuviera pedidos en algún estado, esa combinación aparecería con 0 en lugar de estar ausente, lo que es exactamente lo que necesitas para un informe tipo tabla dinámica.

Generar combinaciones de productos

Otro uso práctico: generar pares de productos que podrían recomendarse juntos. Si quisiéramos buscar qué pares de productos se han comprado en el mismo pedido:

SELECT DISTINCT
    p1.nombre AS producto_1,
    p2.nombre AS producto_2
FROM detalle_pedidos dp1
INNER JOIN detalle_pedidos dp2 ON dp1.pedido_id = dp2.pedido_id
    AND dp1.producto_id < dp2.producto_id
INNER JOIN productos p1 ON dp1.producto_id = p1.id
INNER JOIN productos p2 ON dp2.producto_id = p2.id
ORDER BY p1.nombre
LIMIT 8;
producto_1producto_2
1984Eloquent JavaScript
1984Cable USB-C a Lightning
Banda elástica set x5Zapatillas running pro
Cable USB-C a LightningCamiseta algodón básica
Cable USB-C a LightningCamiseta técnica running
Cable USB-C a LightningClean Code
Cable USB-C a LightningEloquent JavaScript
Cable USB-C a LightningRobot de cocina

Aunque esta consulta usa INNER JOIN en lugar de CROSS JOIN, el concepto subyacente es el mismo: generar combinaciones. La condición dp1.producto_id < dp2.producto_id evita duplicados (no queremos ver tanto "iPhone + Funda" como "Funda + iPhone").

Tamaño del resultado

El peligro principal del CROSS JOIN es el tamaño del resultado. Si una tabla tiene 1.000 filas y otra tiene 10.000, el producto cartesiano genera 10.000.000 filas. Con tablas grandes, esto puede consumir toda la memoria disponible o bloquear el servidor.

-- Para estimar el tamaño antes de ejecutar
SELECT
    (SELECT COUNT(*) FROM productos) AS filas_productos,
    (SELECT COUNT(*) FROM categorias) AS filas_categorias,
    (SELECT COUNT(*) FROM productos) *
    (SELECT COUNT(*) FROM categorias) AS filas_cross_join;
filas_productosfilas_categoriasfilas_cross_join
3016480

480 filas es manejable. Pero imagina hacer un CROSS JOIN entre una tabla de clientes (20.000) y una tabla de productos (50.000): 1.000 millones de filas. Antes de usar CROSS JOIN, siempre calcula mentalmente el tamaño del resultado.

CROSS JOIN accidental

Un error muy común al usar la sintaxis antigua de JOIN (tablas separadas por comas) es olvidar la condición WHERE. Sin ella, obtienes un producto cartesiano no deseado:

-- ERROR común: olvidar la condición WHERE
-- Esto genera 30 × 16 = 480 filas (producto cartesiano completo)
SELECT p.nombre, c.nombre
FROM productos p, categorias c;
 
-- Lo que realmente querías era:
SELECT p.nombre, c.nombre
FROM productos p, categorias c
WHERE p.categoria_id = c.id;

Esta es otra razón por la que la sintaxis moderna con JOIN ... ON es preferible: hace explícita la relación entre tablas y es imposible olvidarla accidentalmente.

Cuándo usar CROSS JOIN

Usa CROSS JOIN cuando necesitas generar explícitamente todas las combinaciones posibles entre dos conjuntos de datos. Los casos más habituales son crear matrices completas para informes (empleado × mes, producto × región), generar calendarios o rangos de fechas combinados con entidades, rellenar datos faltantes en tablas de hechos, y crear datos de prueba con todas las combinaciones posibles.

En todos estos casos, el CROSS JOIN se combina normalmente con un LEFT JOIN posterior para añadir los datos reales donde existan y dejar NULL (o 0) donde no.

Practica con CROSS JOIN

Usa el editor para generar combinaciones con CROSS JOIN:

Simulador SQL
Ctrl+Enter para ejecutar

En el siguiente artículo veremos el Self Join, donde una tabla se une consigo misma para explorar relaciones jerárquicas como la estructura de empleados o las categorías con subcategorías.

Escrito por Eduardo Lázaro