Error SQL · outer join y filtros

LEFT JOIN pierde filas: revisa dónde aplicas el filtro

Si un LEFT JOIN se comporta como un INNER JOIN, comprueba las condiciones sobre la tabla derecha y decide qué filas deben sobrevivir antes de mover el filtro.

Lectura: 14–18 minResultado comprobadoPráctica con pistas

El síntoma: escribes LEFT JOIN, pero desaparecen filas de la tabla izquierda

Un LEFT JOIN conserva las filas de la tabla izquierda aunque no encuentre coincidencia a la derecha, rellenando con NULL las columnas del lado derecho. El problema aparece cuando una condición posterior en WHERE exige un valor concreto de esas columnas: las filas extendidas con NULL dejan de cumplir el filtro.

La consulta puede ser sintácticamente correcta y, aun así, comportarse como un INNER JOIN para esa condición.

Ejemplo: el filtro en WHERE elimina clientes

SQL que pierde filas
WITH clientes(id, nombre) AS (
  VALUES (1, 'Ana'), (2, 'Luis'), (3, 'Marta')
), pedidos(id, cliente_id, estado) AS (
  VALUES (101, 1, 'pagado'), (102, 2, 'pendiente')
)
SELECT c.nombre, p.estado
FROM clientes AS c
LEFT JOIN pedidos AS p
  ON p.cliente_id = c.id
WHERE p.estado = 'pagado'
ORDER BY c.id;
Resultado: solo queda Ana
nombreestado
Anapagado

Luis tiene un pedido pendiente y Marta no tiene pedido. Después del LEFT JOIN, la condición de WHERE descarta ambos casos porque p.estado = 'pagado' no resulta verdadera.

Si quieres conservar todos los clientes, filtra la coincidencia en ON

SQL corregido para esta intención
WITH clientes(id, nombre) AS (
  VALUES (1, 'Ana'), (2, 'Luis'), (3, 'Marta')
), pedidos(id, cliente_id, estado) AS (
  VALUES (101, 1, 'pagado'), (102, 2, 'pendiente')
)
SELECT c.nombre, p.estado
FROM clientes AS c
LEFT JOIN pedidos AS p
  ON p.cliente_id = c.id
 AND p.estado = 'pagado'
ORDER BY c.id;
Resultado: se conservan los tres clientes
nombreestado
Anapagado
LuisNULL
MartaNULL

No muevas condiciones entre ON y WHERE mecánicamente

  1. Define qué filas deben sobrevivir. ¿Quieres todos los clientes o solo clientes con un pedido pagado?
  2. Identifica qué condición define una coincidencia válida. Esa condición puede pertenecer a ON.
  3. Identifica qué condición filtra el resultado final. Esa condición puede pertenecer a WHERE.
  4. Prueba un caso sin coincidencia. Si no tienes una fila así en los datos de prueba, es fácil no detectar el problema.

Error frecuente: creer que ON y WHERE son intercambiables en un outer join

En INNER JOIN suelen coincidir; en LEFT JOIN pueden cambiar el resultado

En un outer join, las filas sin coincidencia se añaden con NULL después de evaluar la condición de unión y antes del filtrado final. Por eso una condición sobre la tabla derecha puede conservar o eliminar esas filas según dónde se aplique.

Práctica correctiva

Intermedia · LEFT JOIN

Conserva todos los clientes y muestra solo pedidos pendientes

Partiendo de las mismas CTE, devuelve Ana, Luis y Marta. La columna de pedido debe tener valor solo cuando exista un pedido pendiente.

Qué debes recordar

  • LEFT JOIN conserva las filas izquierdas antes del filtro final.
  • Un WHERE sobre columnas derechas puede eliminar las filas extendidas con NULL.
  • ON define coincidencias; WHERE filtra el resultado ya unido.
  • Decide primero qué filas deben sobrevivir y después coloca cada condición.

Conceptos relacionados

Fuentes técnicas consultadas