LEFT, RIGHT y FULL JOIN: conservar filas sin coincidencia
Un INNER JOIN responde bien cuando solo nos interesan las filas relacionadas. El problema cambia cuando también necesitamos ver lo que quedó fuera: clientes sin pedidos, productos que nunca se han vendido o registros que aparecen en un origen, pero no en otro.
Las uniones externas conservan esas filas y completan con NULL las columnas para las que no encontraron una coincidencia.
La idea
La dirección de la unión indica qué conjunto se conservará:
LEFT JOINconserva todas las filas de la tabla escrita a la izquierda.RIGHT JOINconserva todas las filas de la tabla escrita a la derecha.FULL JOINconserva las filas de ambos lados, hayan coincidido o no.
Sintaxis
SELECT
a.Columna,
b.OtraColumna
FROM dbo.TablaA AS a
LEFT JOIN dbo.TablaB AS b
ON b.IdRelacionado = a.Id;
Para utilizar RIGHT JOIN o FULL JOIN, sustituimos el tipo de unión. La condición escrita después de ON continúa indicando qué significa que dos filas coincidan.
Ejemplo con LEFT JOIN
Queremos revisar todos los clientes, incluso aquellos que no han realizado pedidos:
SELECT
c.IdCliente,
c.Nombre,
p.IdPedido,
p.Estado
FROM dbo.Cliente AS c
LEFT JOIN dbo.Pedido AS p
ON p.IdCliente = c.IdCliente
ORDER BY
c.IdCliente,
p.IdPedido;
| IdCliente | Nombre | IdPedido | Estado |
|---|---|---|---|
| 1 | Ana Torres | 1 | Confirmado |
| 1 | Ana Torres | 2 | Enviado |
| 2 | Bruno Díaz | 3 | Pendiente |
| 3 | Carla Ruiz | NULL |
NULL |
| 4 | Diego Soto | 4 | Cancelado |
| 5 | Elena Mora | 5 | Confirmado |
Carla permanece porque Cliente está a la izquierda. Como no existe un pedido relacionado con su identificador, las columnas provenientes de Pedido contienen NULL.
Este comportamiento permite encontrar específicamente clientes sin pedidos:
SELECT
c.IdCliente,
c.Nombre
FROM dbo.Cliente AS c
LEFT JOIN dbo.Pedido AS p
ON p.IdCliente = c.IdCliente
WHERE p.IdPedido IS NULL;
RIGHT JOIN
RIGHT JOIN conserva la tabla escrita a la derecha. La mayoría de las consultas puede reescribirse como LEFT JOIN intercambiando el orden de las tablas:
-- Ambas consultas conservan todos los clientes.
FROM dbo.Pedido AS p
RIGHT JOIN dbo.Cliente AS c
ON c.IdCliente = p.IdCliente;
FROM dbo.Cliente AS c
LEFT JOIN dbo.Pedido AS p
ON p.IdCliente = c.IdCliente;
Preferir LEFT JOIN de forma consistente suele facilitar la lectura, pero RIGHT JOIN sigue siendo una construcción válida y puede ayudar al modificar una consulta existente sin reorganizar todos sus elementos.
FULL JOIN
FULL JOIN resulta útil al comparar dos conjuntos. Conserva coincidencias, filas exclusivas de la izquierda y filas exclusivas de la derecha:
SELECT
a.Clave,
a.Valor AS ValorAnterior,
n.Valor AS ValorNuevo
FROM dbo.DatosAnteriores AS a
FULL JOIN dbo.DatosNuevos AS n
ON n.Clave = a.Clave;
Qué conviene comprobar
Una condición sobre la tabla opcional puede convertir accidentalmente un LEFT JOIN en el equivalente práctico de un INNER JOIN:
-- Los clientes sin pedido quedan fuera porque p.Estado es NULL.
WHERE p.Estado = 'Confirmado';
Cuando queremos conservarlos, esa condición puede formar parte de ON o debe contemplar explícitamente el valor nulo. La elección depende de qué filas pretendemos conservar, no de una regla mecánica.
Relacionado con
INNER JOIN: conserva únicamente coincidencias.NULL: representa las columnas sin correspondencia.EXISTSyNOT EXISTS: comprueban si hay filas relacionadas.INTERSECTyEXCEPT: comparan conjuntos compatibles.