Aprende SQL · lección gratuita

Lección 21 · JOINs de múltiples tablas

Resumen

Las preguntas reales casi nunca caben en dos tablas. "¿Cuánto facturó cada departamento de ventas?" exige recorrer una cadena de relaciones: detalle_pedidos → pedidos → clientes / empleados → departamentos. Encadenar varios JOIN es directo: cada uno añade una tabla relacionándola con alguna ya presente en la consulta. La clave es ir paso a paso y mantener un alias claro por tabla.

Sintaxis / Conceptos

Construye la consulta incrementalmente: primero une dos tablas y verifica el resultado; luego añade la tercera, la cuarta, etc. Así detectas pronto si un ON está mal o si una unión multiplica filas inesperadamente.

El orden de los JOIN no cambia el resultado de un encadenamiento de INNER JOIN (son asociativos y conmutativos lógicamente), pero importa cuando hay LEFT JOIN de por medio: una vez que una columna queda NULL por un LEFT, los JOIN posteriores sobre esa columna pueden descartar la fila si no se cuida la lógica.

El error más típico en este nivel: al agregar (COUNT/SUM/etc.) tras varios JOIN, todas las columnas no agregadas del SELECT deben aparecer en el GROUP BY. Si seleccionas c.id, c.empresa, c.pais, agrupa por las tres: GROUP BY c.id, c.empresa, c.pais.

SELECT c.nombre AS categoria, ROUND(SUM(d.cantidad * d.precio_unitario), 0) AS revenue FROM detalle_pedidos d JOIN productos p ON d.producto_id = p.id JOIN categorias c ON p.categoria_id = c.id GROUP BY c.id ORDER BY revenue DESC

Ejemplos

-- Cadena de 5 tablas: facturación por departamento del vendedor
SELECT dep.nombre AS departamento,
       ROUND(SUM(dp.cantidad * dp.precio_unitario * (1 - dp.descuento)), 2) AS facturacion
FROM detalle_pedidos dp
JOIN pedidos p        ON dp.pedido_id = p.id
JOIN empleados e      ON p.empleado_id = e.id
JOIN departamentos dep ON e.departamento_id = dep.id
GROUP BY dep.nombre
ORDER BY facturacion DESC;

-- 4 tablas: top 5 clientes por revenue, con su país y segmento
SELECT c.empresa, c.pais, c.segmento,
       ROUND(SUM(dp.cantidad * dp.precio_unitario * (1 - dp.descuento)), 2) AS revenue
FROM detalle_pedidos dp
JOIN pedidos p   ON dp.pedido_id = p.id
JOIN clientes c  ON p.cliente_id = c.id
GROUP BY c.id, c.empresa, c.pais, c.segmento
ORDER BY revenue DESC
LIMIT 5;

-- Cadena completa (detalle→pedido→cliente→empleado) con nombre de producto y categoría
SELECT p.id AS pedido, c.empresa AS cliente, e.nombre AS vendedor,
       pr.nombre AS producto, cat.nombre AS categoria,
       ROUND(dp.cantidad * dp.precio_unitario * (1 - dp.descuento), 2) AS importe
FROM detalle_pedidos dp
JOIN pedidos p     ON dp.pedido_id = p.id
JOIN clientes c    ON p.cliente_id = c.id
JOIN empleados e   ON p.empleado_id = e.id
JOIN productos pr  ON dp.producto_id = pr.id
JOIN categorias cat ON pr.categoria_id = cat.id
ORDER BY importe DESC
LIMIT 10;
💡 Da a cada tabla un alias corto y memorable (dp, p, c, e, dep, pr, cat). En cadenas de 5-6 tablas, los alias claros son la diferencia entre una consulta legible y un caos imposible de depurar.

Cheatsheet

FormaQué hace
JOIN t1 ON ... JOIN t2 ON ...Encadena varias tablas en una consulta
Empezar por la tabla de detalleFija el grano correcto para los agregados
SUM(cant precio (1-desc))Revenue total tras unir el detalle
Mezclar INNER + LEFTConserva eslabones opcionales en la cadena
Alias cortos por tablaMantiene legible una unión de 4-6 tablas

---

← Auto-relaciones: SELF JOINSubconsultas escalares →

Ver todas las lecciones de Aprende SQL →