Aprende SQL · lección gratuita

Lección 18 · Conservar filas: LEFT y RIGHT JOIN

Resumen

El INNER JOIN descarta las filas sin pareja, pero muchas veces eso es justo lo que NO quieres: necesitas ver al empleado aunque no haya hecho pedidos, o el producto aunque nunca se haya vendido. Para eso existen los OUTER JOIN: conservan todas las filas de un lado y rellenan con NULL las columnas del otro lado cuando no hay coincidencia.

Sintaxis / Conceptos

La tabla "izquierda" es la que aparece en el FROM; la "derecha" es la del JOIN. a LEFT JOIN b = todas las de a + las coincidencias de b. a RIGHT JOIN b = todas las de b + las coincidencias de a. Por tanto a RIGHT JOIN b es idéntico a b LEFT JOIN a.

El detalle más importante y mal entendido es dónde poner los filtros. Compara:

Cuidado al encadenar varios LEFT JOIN (por ejemplo categorias → productos → detalle_pedidos): para conservar las filas hasta el final, todos los joins de la cadena deben ser LEFT. Basta un solo INNER JOIN en medio para que se descarten silenciosamente las filas sin pareja y se pierda la conservación que buscabas.

SELECT p.id, c.empresa AS cliente, e.nombre AS vendedor, p.estado FROM pedidos p JOIN clientes c ON p.cliente_id = c.id JOIN empleados e ON p.empleado_id = e.id LIMIT 5

Ejemplos

-- TODOS los empleados; cuántos pedidos gestionó cada uno (0 si ninguno)
SELECT e.nombre, e.cargo, COUNT(p.id) AS num_pedidos
FROM empleados e
LEFT JOIN pedidos p ON p.empleado_id = e.id
GROUP BY e.id, e.nombre, e.cargo
ORDER BY num_pedidos DESC, e.nombre;

-- Anti-join: productos que NUNCA se vendieron (ids 21-24)
SELECT pr.id, pr.nombre, pr.stock
FROM productos pr
LEFT JOIN detalle_pedidos d ON d.producto_id = pr.id
WHERE d.id IS NULL
ORDER BY pr.id;

-- RIGHT JOIN: parte de pedidos pero conserva TODOS los empleados (espejo del LEFT)
SELECT e.nombre, COUNT(p.id) AS num_pedidos
FROM pedidos p
RIGHT JOIN empleados e ON p.empleado_id = e.id
GROUP BY e.id, e.nombre
ORDER BY num_pedidos DESC, e.nombre;
💡 Para contar coincidencias en un LEFT JOIN usa COUNT(p.id) (cuenta solo lo no nulo), nunca COUNT(*), que daría 1 incluso para los empleados sin pedidos.

Cheatsheet

FormaQué hace
a LEFT JOIN b ON ...Todas las de a + coincidencias de b (NULL si falta)
a RIGHT JOIN b ON ...Todas las de b + coincidencias de a
LEFT JOIN b ... WHERE b.id IS NULLAnti-join: filas de a sin pareja en b
Filtro en ON (lado derecho)Conserva las filas sin pareja
Filtro en WHERE (lado derecho)Elimina los NULL (vuelve a INNER)

---

← Combinar tablas: INNER JOINFULL OUTER JOIN y CROSS JOIN →

Ver todas las lecciones de Aprende SQL →