Contenido de esta guía
Respuesta rápida
INNER JOIN conserva solo las coincidencias. LEFT JOIN conserva todas las filas de la tabla izquierda y completa con NULL cuando no encuentra pareja.
La pregunta que decide el JOIN
Antes de escribir la consulta, formula una pregunta observable:
- “Muéstrame clientes que tienen pedidos” conduce a
INNER JOIN. - “Muéstrame todos los clientes, tengan o no pedidos” conduce a
LEFT JOIN.
La tabla situada a la izquierda de LEFT JOIN es la que se conserva completa. Cambiar el orden de las tablas cambia el significado.
| Aspecto | INNER JOIN | LEFT JOIN |
|---|---|---|
| Filas con coincidencia | Se conservan | Se conservan |
| Filas izquierdas sin coincidencia | Desaparecen | Se conservan con columnas derechas en NULL |
| Pregunta típica | ¿Qué elementos están relacionados? | ¿Qué elementos existen, incluso sin relación? |
Ejemplo: clientes y pedidos
SELECT c.nombre, p.id AS pedido_id
FROM clientes AS c
INNER JOIN pedidos AS p
ON p.cliente_id = c.id
ORDER BY c.id, p.id;Solo aparecen clientes con al menos un pedido. Un cliente puede producir varias filas porque cada pedido es una coincidencia distinta.
SELECT c.nombre, p.id AS pedido_id
FROM clientes AS c
LEFT JOIN pedidos AS p
ON p.cliente_id = c.id
ORDER BY c.id, p.id;Ahora también aparecen Pablo Sanz y Mario Gil. Como no tienen pedidos, pedido_id vale NULL.
El filtro que puede convertir el LEFT JOIN
Una condición sobre la tabla derecha colocada en WHERE se evalúa después de formar el resultado. Si exige un valor concreto, las filas sin coincidencia no la cumplen porque contienen NULL.
SELECT c.nombre, COUNT(p.id) AS enviados
FROM clientes AS c
LEFT JOIN pedidos AS p
ON p.cliente_id = c.id
AND p.estado = 'enviado'
GROUP BY c.id, c.nombre
ORDER BY c.id;La condición de estado forma parte de la coincidencia. Los clientes sin pedidos enviados se mantienen y su conteo es 0. Si escribieras WHERE p.estado = 'enviado', desaparecerían.
Errores frecuentes
Interpretar los NULL como datos defectuosos
En un LEFT JOIN, un NULL de la tabla derecha puede significar simplemente que no hubo coincidencia.
Esperar una fila por cliente sin agrupar
Un cliente con tres pedidos produce tres coincidencias. Para obtener una fila por cliente debes agregar, elegir una sola coincidencia o definir otra regla.
Filtrar la tabla derecha en WHERE sin revisar el objetivo
Ese filtro puede eliminar justo las filas sin relación que pretendías conservar.
Práctica guiada
Cuenta pedidos enviados para todos los clientes
Devuelve el identificador, nombre y cantidad de pedidos enviados de cada cliente. Deben aparecer también quienes tienen cero pedidos enviados.
clientes.ON.COUNT(p.id) devuelve 0 cuando no existe una coincidencia no nula.Solución razonada
SELECT c.id,
c.nombre,
COUNT(p.id) AS pedidos_enviados
FROM clientes AS c
LEFT JOIN pedidos AS p
ON p.cliente_id = c.id
AND p.estado = 'enviado'
GROUP BY c.id, c.nombre
ORDER BY c.id;El LEFT JOIN conserva los doce clientes. La condición en ON limita qué pedidos cuentan sin eliminar al cliente.
Compatibilidad
La forma básica de INNER JOIN y LEFT JOIN es portable entre los motores principales. Pueden variar las reglas sobre alias, agrupación, optimización y funciones posteriores, pero la conservación de filas descrita aquí es el modelo común.
Qué debes recordar
INNER JOINmuestra coincidencias.LEFT JOINconserva la tabla izquierda.- Los
NULLderechos señalan ausencia de coincidencia. - Un filtro derecho en
WHEREpuede eliminar las filas conservadas.