Los JOINs son la operación más característica de las bases de datos relacionales. Permiten combinar filas de dos o más tablas basándose en una condición entre columnas, normalmente entre una clave foránea y la clave primaria a la que apunta. Sin JOINs, toda la información tendría que guardarse en una sola tabla gigante, duplicando datos y haciendo imposible el mantenimiento.
INNER JOIN es el tipo de JOIN más común: devuelve solo las filas que tienen correspondencia en ambas tablas. Si un cliente no tiene pedidos, no aparece en un INNER JOIN entre clientes y pedidos.
El problema del producto cartesiano
-- Sin condición de JOIN, se obtiene el producto cartesiano: -- cada fila de clientes se combina con cada fila de pedidos -- Si hay 4 clientes y 10 pedidos → 40 filas, todas incorrectas SELECT * FROM clientes, pedidos; -- ¡NO hagas esto!
INNER JOIN: la sintaxis correcta
-- Sintaxis estándar (SQL-92, recomendada) SELECT c.nombre, c.email, p.id AS pedido, p.estado, p.total FROM pedidos p INNER JOIN clientes c ON c.id = p.id_cliente; -- La palabra INNER es opcional; JOIN a secas es INNER JOIN SELECT c.nombre, p.estado, p.total FROM pedidos p JOIN clientes c ON c.id = p.id_cliente;
Alias de tabla
Con alias, las consultas son más cortas y legibles. Se definen directamente después del nombre de la tabla:
-- Sin alias (verboso) SELECT clientes.nombre, pedidos.total FROM pedidos INNER JOIN clientes ON clientes.id = pedidos.id_cliente; -- Con alias (limpio) SELECT c.nombre, p.total FROM pedidos p INNER JOIN clientes c ON c.id = p.id_cliente;
JOIN con tres tablas
-- Detalle de líneas de pedido: pedido, cliente, producto
SELECT
p.id AS pedido_id,
c.nombre AS cliente,
pr.nombre AS producto,
lp.cantidad,
lp.precio_ud,
ROUND(lp.cantidad * lp.precio_ud, 2) AS subtotal
FROM lineas_pedido lp
JOIN pedidos p ON p.id = lp.id_pedido
JOIN clientes c ON c.id = p.id_cliente
JOIN productos pr ON pr.id = lp.id_producto
ORDER BY p.id, pr.nombre;
JOIN con cinco tablas: incluir la categoría
SELECT
p.id AS pedido_id,
c.nombre AS cliente,
cat.nombre AS categoria,
pr.nombre AS producto,
lp.cantidad,
lp.precio_ud
FROM lineas_pedido lp
JOIN pedidos p ON p.id = lp.id_pedido
JOIN clientes c ON c.id = p.id_cliente
JOIN productos pr ON pr.id = lp.id_producto
JOIN categorias cat ON cat.id = pr.id_categoria
ORDER BY p.id;
Filtrar en el JOIN o en el WHERE
-- Estas dos consultas son equivalentes con INNER JOIN: -- Condición en el WHERE: SELECT c.nombre, p.total FROM pedidos p JOIN clientes c ON c.id = p.id_cliente WHERE p.estado = 'pagado'; -- Condición en el ON: SELECT c.nombre, p.total FROM pedidos p JOIN clientes c ON c.id = p.id_cliente AND p.estado = 'pagado'; -- Nota: con LEFT JOIN NO son equivalentes (ver capítulo siguiente)
USING: cuando las columnas tienen el mismo nombre
-- Si la columna de unión se llama igual en ambas tablas, puedes usar USING -- (En el esquema del curso las FKs tienen nombres diferentes, pero el concepto aplica) SELECT nombre, email FROM usuarios u JOIN pedidos p USING (id_usuario);
El INNER JOIN solo devuelve filas con correspondencia en ambas tablas. Si necesitas incluir filas sin correspondencia (por ejemplo, clientes que aún no han hecho ningún pedido), usa LEFT JOIN, que se explica en el siguiente capítulo.
