SQL LEFT JOIN: filas con coincidencia opcional
SQL LEFT JOIN devuelve cada fila de la tabla izquierda y adjunta las filas coincidentes de la tabla derecha. En términos de SQL, es un SQL outer join: cuando no existe coincidencia, las columnas del lado derecho se rellenan con NULL. Úsalo cuando necesites todos los registros de una tabla, exista o no información relacionada, por ejemplo al listar todos los clientes hayan hecho pedidos o no. LEFT JOIN y LEFT OUTER JOIN son palabras clave idénticas; OUTER es opcional.
Ejemplo de SQL LEFT JOIN para devolver todas las filas
Salida:
La salida aparecerá aquí...
Salida:
+---------+-------+
| cliente | total |
+---------+-------+
| Alma | 79 |
| Alma | 150 |
| Ben | NULL |
| Cara | 45 |
+---------+-------+
4 row(s)
Cómo funciona este ejemplo
customerscontiene tres personas;orderscontiene tres pedidos enlazados porcustomer_id.LEFT JOIN orders o ON o.customer_id = c.idempareja cada cliente con cada pedido que coincide con suid. Alma tiene dos pedidos, por eso genera dos filas de salida.- Ben no tiene pedidos. LEFT JOIN conserva su fila y rellena
o.totalcon NULL en lugar de excluirlo del resultado (que es lo que haría INNER JOIN). ORDER BY c.id, o.idmantiene la salida agrupada por cliente y estable dentro de cada cliente. El NULL en la columnatotalde Ben indica ausencia de coincidencia, no un pedido con valor cero.
ON vs WHERE: por qué importa dónde filtras
Poner un filtro de la tabla derecha en WHERE en lugar de ON es el error más común con LEFT JOIN: convierte silenciosamente el outer join en un inner join.
-- Incorrecto: WHERE elimina a Ben porque su o.total es NULL
SELECT c.name, o.total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.total > 50;
-- Correcto: ON filtra durante la coincidencia del join; Ben se conserva con NULL
SELECT c.name, o.total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id AND o.total > 50;
Las condiciones en ON se evalúan durante la unión: las filas izquierdas sin coincidencia siguen apareciendo con NULL. WHERE se aplica después de la unión, así que elimina cualquier fila donde la columna derecha sea NULL, justo las filas que LEFT JOIN estaba diseñado para conservar.
Anti-join: encontrar filas sin coincidencia
LEFT JOIN combinado con una comprobación IS NULL sobre una columna de la tabla derecha es una forma estándar de encontrar registros relacionados faltantes:
SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;
Esto devuelve solo a Ben, el cliente con cero pedidos. El patrón funciona porque o.id es NULL únicamente para filas izquierdas sin coincidencia. NOT EXISTS logra el mismo resultado y puede ser más claro cuando no necesitas columnas de la tabla derecha en la salida.
LEFT JOIN vs INNER JOIN
| LEFT JOIN | INNER JOIN |
|---|---|
| Todas las filas de la izquierda, NULL para columnas derechas sin coincidencia | Solo filas que coinciden en ambos lados |
| Conteo de filas >= conteo de filas de la tabla izquierda | Conteo de filas <= conteo de filas de la tabla más pequeña |
| Úsalo cuando las filas sin coincidencia tienen significado (reportes, comprobaciones de integridad) | Úsalo cuando cada fila del resultado debe tener datos válidos de ambas tablas |
Regla: empieza con LEFT JOIN cuando sea importante conservar todas las filas de la izquierda. Cambia a INNER JOIN cuando las filas sin coincidencia no importan o son inválidas.
Errores comunes con SQL LEFT JOIN
Multiplicación de filas en joins uno a muchos
LEFT JOIN produce una fila de salida por cada par coincidente. Si un cliente tiene diez pedidos, ese cliente aparece diez veces. Agregar sin tener esto en cuenta infla los totales.
-- Incorrecto: cuenta filas de pedidos, no clientes
SELECT COUNT(*) FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;
-- Correcto: cuenta clientes distintos
SELECT COUNT(DISTINCT c.id) FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;
Usar SELECT * con joins
SELECT * en una consulta con join devuelve nombres de columna duplicados (por ejemplo, c.id y o.id), lo que causa confusión en el código de aplicación. Lista siempre las columnas que necesitas.
Notas de rendimiento
Indexa la clave de unión en la tabla derecha (orders.customer_id) para que el motor pueda buscar coincidencias en lugar de escanear. Para tablas derechas grandes donde solo importa un subconjunto de filas, prefiltra con una subconsulta o mueve el filtro a la cláusula ON, no a WHERE, para reducir el trabajo del join sin romper la semántica de LEFT JOIN.
Preguntas frecuentes
¿Cuál es la diferencia entre LEFT JOIN y LEFT OUTER JOIN?
Ninguna. LEFT JOIN y LEFT OUTER JOIN son sinónimos definidos por el estándar SQL. Todas las bases de datos principales (PostgreSQL, MySQL, SQLite, SQL Server, Oracle) los tratan igual. La mayoría de desarrolladores omiten OUTER por brevedad.
¿Por qué mi LEFT JOIN devuelve menos filas después de agregar una cláusula WHERE?
Un filtro WHERE sobre una columna de la tabla derecha elimina las filas extendidas con NULL, y convierte el LEFT JOIN en un INNER JOIN efectivo. Mueve la condición a la cláusula ON para conservar en el resultado las filas izquierdas sin coincidencia.
¿Cuándo debo usar LEFT JOIN en lugar de INNER JOIN?
Usa LEFT JOIN cuando las filas del lado izquierdo deban aparecer en la salida independientemente de coincidencias: reportes de completitud, comprobaciones de datos faltantes y enriquecimiento opcional. Usa INNER JOIN cuando solo las filas coincidentes sean válidas y debas excluir las no coincidentes.