Tipos de JOIN en SQL: guía con ejemplos

Tipos de JOIN en SQL: guía con ejemplos

Un JOIN en SQL combina filas de dos tablas mediante una condición relacionada. Es la operación que permite responder preguntas como “¿qué cliente hizo cada pedido?” o “¿qué productos todavía no se han vendido?” sin duplicar toda la información en una sola tabla.

La elección del JOIN importa: un tipo incorrecto puede eliminar registros válidos, multiplicar filas o convertir ausencias en resultados engañosos. Esta guía explica INNER, LEFT, RIGHT, FULL y CROSS JOIN con un mismo ejemplo para que la diferencia sea visible.

Tablas del ejemplo

Supón una tabla clientes:

cliente_id nombre
1 Ana
2 Bruno
3 Carla

Y una tabla pedidos:

pedido_id cliente_id total
101 1 80
102 1 35
103 4 50

Ana tiene dos pedidos, Bruno y Carla ninguno, y el pedido 103 apunta a un cliente que no aparece en la primera tabla. Ese caso deliberadamente imperfecto permite ver qué conserva cada unión. En un diseño correcto, una clave foránea normalmente impediría el cliente 4 inexistente.

INNER JOIN: solo coincidencias

INNER JOIN devuelve filas cuando la condición se cumple en ambas tablas:

SELECT c.nombre, p.pedido_id, p.total
FROM clientes AS c
INNER JOIN pedidos AS p
  ON p.cliente_id = c.cliente_id;

El resultado contiene dos filas de Ana. Bruno, Carla y el pedido huérfano quedan fuera. Es apropiado cuando la pregunta requiere únicamente entidades relacionadas, pero no cuando necesitas auditar ausencias.

LEFT JOIN: conserva la tabla izquierda

SELECT c.nombre, p.pedido_id, p.total
FROM clientes AS c
LEFT JOIN pedidos AS p
  ON p.cliente_id = c.cliente_id;

Ahora aparecen todos los clientes. Las columnas del pedido son NULL para Bruno y Carla. Para encontrar clientes sin pedidos, filtra la clave del lado derecho:

SELECT c.cliente_id, c.nombre
FROM clientes AS c
LEFT JOIN pedidos AS p
  ON p.cliente_id = c.cliente_id
WHERE p.pedido_id IS NULL;

No filtres con WHERE p.total > 0 si quieres conservar clientes sin pedidos: esa condición descarta los NULL y hace que el resultado se comporte como un INNER JOIN. Si el filtro pertenece a la relación, colócalo en ON.

RIGHT JOIN y FULL OUTER JOIN

RIGHT JOIN conserva todas las filas de la tabla derecha. En el ejemplo mostraría los tres pedidos, incluido el 103 con datos de cliente nulos. Casi siempre puede reescribirse como LEFT JOIN intercambiando el orden de las tablas, lo que suele facilitar la lectura.

FULL OUTER JOIN conserva coincidencias y ausencias de ambos lados:

SELECT c.nombre, p.pedido_id
FROM clientes AS c
FULL OUTER JOIN pedidos AS p
  ON p.cliente_id = c.cliente_id;

Es útil para conciliaciones entre sistemas. Debes confirmar que tu motor lo admite; cuando no existe soporte directo, puede simularse con dos consultas y UNION ALL, excluyendo la intersección repetida.

CROSS JOIN: producto cartesiano

CROSS JOIN combina cada fila izquierda con cada fila derecha. Tres clientes y tres pedidos producen nueve filas:

SELECT c.nombre, p.pedido_id
FROM clientes AS c
CROSS JOIN pedidos AS p;

No requiere ON. Resulta útil para generar todas las combinaciones de fechas, sucursales y escenarios, pero puede crecer de forma explosiva: 10.000 por 10.000 son 100 millones de filas.

Cómo evitar filas duplicadas inesperadas

Un JOIN no “duplica” arbitrariamente. Devuelve una fila por cada pareja que cumple la condición. Si una clave aparece dos veces en una tabla y tres en la otra, esa clave genera seis combinaciones.

Antes de unir:

  1. Define la granularidad de cada tabla.
  2. Comprueba si la clave debería ser única.
  3. Cuenta filas antes y después.
  4. Busca duplicados con GROUP BY clave HAVING COUNT(*) > 1.
  5. No uses DISTINCT para ocultar una relación mal definida.

Los índices de bases de datos sobre las columnas de unión pueden mejorar el rendimiento, pero no corrigen una condición lógica equivocada.

JOIN con varias condiciones

Una relación puede necesitar más de una columna:

SELECT v.*, m.objetivo
FROM ventas AS v
LEFT JOIN metas AS m
  ON m.sucursal_id = v.sucursal_id
 AND m.mes = v.mes;

Si unes solo por sucursal, cada venta podría combinarse con las metas de todos los meses. El criterio debe representar la clave real del nivel de detalle.

Guía de elección rápida

Necesidad JOIN
Solo registros relacionados INNER
Todo lo principal, exista o no detalle LEFT
Todo el lado derecho RIGHT
Conciliar ambos universos FULL OUTER
Crear todas las combinaciones CROSS

Para practicar dentro de consultas mayores, combina esta guía con CTE en SQL y revisa siempre el plan lógico desde FROM y JOIN antes de agregar filtros.

Preguntas frecuentes

¿Qué diferencia hay entre JOIN e INNER JOIN?
Ninguna en la mayoría de motores: escribir JOIN sin calificativo equivale a INNER JOIN. Expresar INNER puede hacer más evidente la intención.

¿Cuál es el JOIN más utilizado?
INNER JOIN y LEFT JOIN cubren la mayoría de los análisis. INNER conserva coincidencias; LEFT también conserva las entidades sin detalle.

¿Por qué un JOIN aumenta el número de filas?
Porque una clave tiene varias coincidencias. Una relación muchos a muchos produce todas las combinaciones válidas entre ambos conjuntos.

¿Dónde se filtra la tabla derecha en un LEFT JOIN?
Pon en ON las condiciones que deban limitar coincidencias sin eliminar filas izquierdas. Un filtro derecho en WHERE puede descartar los NULL resultantes.

¿Se puede unir más de dos tablas?
Sí. Encadena varios JOIN, pero valida la granularidad después de cada relación para detectar multiplicaciones antes de agregar métricas.

¿Necesito una clave foránea para hacer JOIN?
No es obligatoria para la consulta, aunque una restricción de clave foránea ayuda a preservar integridad y documentar la relación esperada.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir