Al terminar, podrás
- Elegir la tabla que debe conservar todas sus filas.
- Separar condiciones de relación y condiciones de filtrado.
- Detectar duplicados y ausencias producidos por la cardinalidad.
Recupera lo aprendido: Para conservar a clientes sin pedidos enviados, ¿el filtro de estado debe ir en ON o en WHERE?
La idea clave
Antes de elegir un JOIN, formula la pregunta de conservación: “¿qué entidad debe aparecer aunque no tenga coincidencia?”. Si la respuesta es ninguna, suele bastar INNER JOIN; si una tabla debe mantenerse completa, colócala a la izquierda de LEFT JOIN.
Después del JOIN: comprueba la cantidad de filas. Una relación uno a varios repite la fila del lado uno.
Mapa de decisión
-- Solo coincidencias
FROM tabla_a AS a
JOIN tabla_b AS b ON b.a_id = a.id
-- Conservar todas las filas de a
FROM tabla_a AS a
LEFT JOIN tabla_b AS b ON b.a_id = a.idEjemplo paso a paso
Buscaremos pedidos sin pago. Los pedidos deben conservarse aunque no exista coincidencia en pagos.
SELECT p.id AS pedido_id, p.estado, p.total
FROM pedidos AS p
LEFT JOIN pagos AS pg ON pg.pedido_id = p.id
WHERE pg.id IS NULL
ORDER BY p.id;| pedido_id | estado | total |
|---|---|---|
| 103 | cancelado | 24,90 |
| 108 | cancelado | 249,00 |
| 116 | cancelado | 999,00 |
Cómo funciona
LEFT JOINconserva los 18 pedidos.- Los pedidos sin pago reciben
NULLen las columnas depagos. WHERE pg.id IS NULLconserva únicamente esas ausencias.
Un error habitual
Convertir sin querer un LEFT JOIN en INNER JOIN
SELECT c.nombre, p.id
FROM clientes AS c
LEFT JOIN pedidos AS p ON p.cliente_id = c.id
WHERE p.estado = 'enviado';Los clientes sin pedidos tienen p.estado = NULL y quedan fuera del WHERE. Si deben aparecer con cero coincidencias enviadas, mueve p.estado = 'enviado' a la cláusula ON.
Practica con datos
Laboratorio SQL
Resuelve la consulta
Escribe una consulta que devuelva todos los clientes y el número de pedidos enviados de cada uno, incluido cero.
Resultado esperado: 12 filas con nombre, enviados. El orden de las filas no importa.
Ver tablas y datos
Cargando la estructura del ejercicio…
Clientes va a la izquierda.
El estado enviado se filtra dentro de ON.
Cuenta p.id, no *.
Solución
SELECT c.nombre, COUNT(p.id) AS enviados FROM clientes AS c LEFT JOIN pedidos AS p ON c.id = p.cliente_id AND p.estado = 'enviado' GROUP BY c.id, c.nombre;Esta forma conserva todos los clientes y cuenta únicamente coincidencias enviadas.
Puedes consultar la solución y volver a intentarlo. La práctica se completa cuando tu consulta funciona.
La consulta usa datos ficticios y se ejecuta solo en este navegador.
Ronda autónoma
Lista todos los pedidos con su método de pago
Devuelve pedido_id, estado y metodo. Los pedidos sin pago deben aparecer con NULL. Ordena por identificador.
Ver la solución
SELECT p.id AS pedido_id,
p.estado,
pg.metodo
FROM pedidos AS p
LEFT JOIN pagos AS pg ON pg.pedido_id = p.id
ORDER BY p.id;El resultado contiene 18 filas. Los pedidos 103, 108 y 116 muestran NULL en metodo.
Comprueba si puedes explicarlo
Un cliente no tiene pedidos enviados. ¿Qué dan COUNT(*) y COUNT(p.id) tras el LEFT JOIN filtrado en ON?
Ver respuesta razonada
Dan 1 y 0. COUNT(*) cuenta la fila conservada; COUNT(p.id) ignora el identificador NULL. Para contar pedidos, cuenta la clave del pedido.
Responde antes de abrir la explicación. Si necesitaste ayuda, cierra la respuesta y vuelve a explicarlo con tus palabras antes de dar la lección por aprendida.
Qué debes recordar
- Decide qué filas deben conservarse antes de elegir el tipo de JOIN.
- La cláusula
ONdefine coincidencias;WHEREfiltra el resultado posterior. - Comprueba la cardinalidad y cuenta una columna de la tabla relacionada cuando necesites ceros.
A continuación: continúa con subconsultas.
Fuentes técnicas consultadas
Estas fuentes oficiales respaldan la sintaxis y los matices señalados en la lección.