SQL JOIN explicado: LEFT vs INNER

Olvida los diagramas de Venn. Un JOIN empareja filas y las pega una al lado de la otra. Solo hay una pregunta que separa los tipos de JOIN: ¿qué ocurre con una fila de la izquierda que no tiene pareja? INNER la descarta. LEFT la conserva y rellena el otro lado con NULL.

🎙️ Publicado y grabado:

🎧 Escuchar esta guía

El punto de partida: dos tablas, un enlace

-- users                        -- orders
-- id | name                    -- id | user_id | amount
-- 1  | Ada                     -- 1  | 1       | 19.99
-- 2  | Lin                     -- 2  | 1       | 5.00
-- 3  | Sam                     -- 3  | 2       | 42.50
--          (Sam no tiene pedidos: fíjate en lo que le ocurre)

INNER JOIN: solo las coincidencias

SELECT users.name, orders.amount
FROM orders
JOIN users ON orders.user_id = users.id;

-- Ada | 19.99
-- Ada |  5.00      ← Ada coincide dos veces → aparece dos veces
-- Lin | 42.50
-- (Sam no aparece. Sin coincidencia no hay fila. Eso es INNER.)

LEFT JOIN: conserva todas las filas de la izquierda

SELECT users.name, orders.amount
FROM users
LEFT JOIN orders ON orders.user_id = users.id;

-- Ada | 19.99
-- Ada |  5.00
-- Lin | 42.50
-- Sam | NULL       ← se conserva; el lado derecho se rellena con NULL

¿Qué tabla es la «izquierda»? La que aparece después de FROM. «Todos los usuarios y sus pedidos» → users a la izquierda. «Todos los pedidos y su usuario» → orders a la izquierda. Di la frase en voz alta: la frase elige la tabla.

El uso clásico: encontrar filas sin coincidencia

-- "usuarios que nunca han hecho un pedido"
SELECT users.name
FROM users
LEFT JOIN orders ON orders.user_id = users.id
WHERE orders.id IS NULL;      -- la ausencia de coincidencia ES el filtro
-- → Sam
El error que se come una tarde entera
Añade una condición normal sobre la tabla de la derecha al WHERE de un LEFT JOIN —WHERE orders.amount > 10— y las filas con NULL desaparecen: NULL > 10 no es verdadero, así que Sam queda fuera y el LEFT JOIN se comporta como INNER sin avisar. Solución: coloca las condiciones de la tabla derecha en la cláusula ONON orders.user_id = users.id AND orders.amount > 10— para filtrar las coincidencias sin perder las filas que no tienen pareja.

Tres tablas: es lo mismo, dos veces

SELECT u.name, o.amount, p.title
FROM orders o
JOIN users    u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id;
-- cada JOIN añade otra tabla a una fila que se va ensanchando.
-- los alias cortos (o, u, p) mantienen la consulta legible.

El resto de la familia, sin rodeos

RIGHT JOIN   -- es un LEFT JOIN con las tablas intercambiadas. casi nadie
             -- lo escribe; pásalo a LEFT y conserva un único modelo mental.
FULL JOIN    -- conserva las filas sin pareja de AMBOS lados. raro; auditorías.
CROSS JOIN   -- todas las combinaciones (sin ON). tallas × colores = variantes.
📚 Esta es una página de nuestra serie de SQL. El curso intensivo completo incluye trampas de NULL, GROUP BY y la historia de terror de UPDATE: SQL en 10 minutos →