🎯 Quedan pocos días este mes Apoya SQLTest.online y ayúdanos a mantener la práctica de SQL gratuita para todos. Dona hoy →
Código SQL copiado al portapapeles

Escenarios prácticos de SQL JOIN

Lección 5.8 · Tiempo de lectura: ~8 min · Tareas de práctica ↓

Esta lección reúne escenarios prácticos de SQL JOIN: unir varias tablas siguiendo las relaciones del esquema, agregar datos unidos, encontrar datos faltantes y evitar los dos errores de join más comunes: totales inflados y joins externos que pierden sus filas.

Ya conoces los tipos de join; ahora la tarea es aplicarlos a preguntas reales. La mayoría de las consultas de informes siguen los mismos pasos: encontrar las tablas que tienen los datos, conectarlas por sus claves, filtrar y agregar.

Joins SQL en la práctica: un camino por el esquema del cliente al pago y de la película a la categoría, la agregación después de un join y la multiplicación de filas que infla las sumas

Planificar el camino del join

Empieza por la pregunta y busca un camino entre tablas en el diagrama de la base de datos. "Ingresos por categoría de película" necesita category, luego film_category, inventory, rental y por último payment:

SELECT c.name AS category,
       COUNT(p.payment_id) AS payments,
       SUM(p.amount) AS revenue
FROM category AS c
INNER JOIN film_category AS fc ON fc.category_id = c.category_id
INNER JOIN inventory AS i ON i.film_id = fc.film_id
INNER JOIN rental AS r ON r.inventory_id = i.inventory_id
INNER JOIN payment AS p ON p.rental_id = r.rental_id
GROUP BY c.name
ORDER BY revenue DESC;

Resultado: 16 categorías ordenadas por ingresos; Sports y Sci-Fi encabezan la lista.

La tabla film en sí no hace falta: film_category e inventory guardan film_id, así que se pueden unir directamente. Une solo las tablas que tienen datos o que son necesarias para conectarlas.


Agregar después de un join

El gasto total de cada cliente:

SELECT c.customer_id,
       c.first_name,
       c.last_name,
       COUNT(*) AS payments,
       SUM(p.amount) AS total_spent
FROM customer AS c
INNER JOIN payment AS p ON p.customer_id = c.customer_id
GROUP BY c.customer_id, c.first_name, c.last_name
ORDER BY total_spent DESC
LIMIT 10;

Resultado: los 10 clientes que más gastaron.

Agrupa por la clave (customer_id), no solo por el nombre: dos clientes distintos pueden tener el mismo nombre.


La trampa de la multiplicación: totales inflados

Un join multiplica filas: un cliente con 30 pagos y 30 alquileres se convierte en 900 filas si ambas tablas se unen al cliente a la vez. Cualquier suma sobre ese resultado está mal.

-- Mal: los pagos se multiplican por los alquileres
SELECT c.customer_id,
       SUM(p.amount) AS total_spent
FROM customer AS c
INNER JOIN payment AS p ON p.customer_id = c.customer_id
INNER JOIN rental AS r ON r.customer_id = c.customer_id
WHERE c.customer_id = 1
GROUP BY c.customer_id;

Resultado: 3797,76 en lugar de los 118,68 reales: cada uno de los 32 pagos del cliente se contó una vez por cada uno de sus 32 alquileres.

La regla: no unas dos tablas "muchos" independientes a la misma fila en una sola consulta. Aquí la tabla rental ni siquiera hace falta. Cuando necesites totales de dos tablas así, agrega primero cada una por separado; aprenderás cómo con subconsultas y CTE en el módulo 6.


Encontrar datos faltantes

LEFT JOIN ... WHERE right_key IS NULL encuentra filas sin coincidencia. Clientes que no alquilaron nada desde el 23 de agosto de 2005:

SELECT c.customer_id, c.first_name, c.last_name
FROM customer AS c
LEFT JOIN rental AS r ON r.customer_id = c.customer_id
                     AND r.rental_date >= '2005-08-23'
WHERE r.rental_id IS NULL
ORDER BY c.customer_id;

Resultado: los clientes sin alquileres en los últimos días de los datos.

Fíjate en la condición de fecha: está en ON, porque limita qué alquileres cuentan como coincidencia. En WHERE eliminaría a todos los clientes sin coincidencia y la consulta no devolvería nada.


WHERE u ON en joins externos

El ejemplo anterior muestra la regla general para LEFT JOIN:

Condición sobreDónde ponerlaEfecto
la tabla derecha, para limitar coincidenciasONLas filas izquierdas se quedan; solo se filtran las coincidencias
la tabla izquierdaWHERELas filas izquierdas se quitan del resultado
la clave de la tabla derecha IS NULLWHEREConserva solo las filas sin coincidencia (anti-join)

Para INNER JOIN, ON y WHERE dan el mismo resultado, así que el lugar es cuestión de legibilidad.


Conclusiones clave:

  • Planifica el camino del join por el esquema y une solo las tablas que necesitas.
  • Agrupa por claves, no solo por nombres.
  • Unir dos tablas "muchos" a la misma fila multiplica las filas e infla sumas y conteos.
  • LEFT JOIN ... WHERE key IS NULL encuentra datos faltantes.
  • En los joins externos, las condiciones sobre la tabla derecha van en ON.

Preguntas frecuentes

¿Cómo uno más de dos tablas en SQL?

Agrega un JOIN ... ON ... por cada tabla, siguiendo las claves foráneas del esquema. Cada join conecta una tabla nueva con las que ya están en la consulta.

¿Por qué mi SUM devuelve un número mucho mayor después de un JOIN?

Porque el join multiplicó las filas: cada fila de una tabla se repitió por cada fila coincidente de otra. Quita las tablas que no necesitas, o agrega cada tabla por separado antes de unir los resultados.

¿Un filtro va en ON o en WHERE?

Para INNER JOIN da lo mismo. Para LEFT JOIN, una condición sobre la tabla derecha va en ON; en WHERE elimina las filas sin coincidencia y convierte el join externo en uno interno.

Intenta resolver las siguientes tareas para reforzar lo que aprendiste en esta lección.

  1. Catálogo de productos