Aprende SQL · lección gratuita
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.
JOIN: cada JOIN ... ON conecta la tabla nueva con una columna de una tabla ya unida. El orden de escritura es flexible mientras cada ON referencie algo ya disponible.detalle_pedidos, 80 filas). Cada línea de pedido es una venta; las demás tablas aportan contexto (cliente, vendedor, departamento).cantidad precio_unitario (1 - descuento). Se calcula sobre detalle_pedidos y se suma con SUM(...) tras agrupar.JOIN: puedes combinar INNER y LEFT en una misma cadena. Usa LEFT cuando un eslabón pueda no tener pareja y aun así quieras conservar la fila.JOIN: si una tabla multiplica filas (un pedido tiene varias líneas), los COUNT/SUM se inflan. Agrupa al grano correcto.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 sí 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
-- 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.
| Forma | Qué hace |
|---|---|
JOIN t1 ON ... JOIN t2 ON ... | Encadena varias tablas en una consulta |
| Empezar por la tabla de detalle | Fija el grano correcto para los agregados |
SUM(cant precio (1-desc)) | Revenue total tras unir el detalle |
Mezclar INNER + LEFT | Conserva eslabones opcionales en la cadena |
| Alias cortos por tabla | Mantiene legible una unión de 4-6 tablas |
---