JOIN: dos tablas en una consulta
En resumen: JOIN … ON combina una fila de una tabla con la fila de otra tabla a la que apunta su clave foránea, por ejemplo un pedido con su cliente, y conserva solo las filas que tienen pareja.
Problema
Pedidos con nombres
La empresa de mensajería quiere una lista: número de pedido, fecha y nombre del cliente. El número y la fecha están en orders, el nombre está en customers.
En la última lección lo hicimos con dos consultas y pasamos el número de una a otra a mano. Con 60 pedidos son 60 búsquedas. Necesitamos una consulta que encuentre sola el cliente de cada pedido.
La idea
JOIN … ON
JOIN pone junto a cada fila de una tabla la fila correspondiente de la otra. ON dice qué fila corresponde a cuál:
Para cada pedido la base busca el cliente cuyo customers.id es igual a orders.customer_id, y los pega en una sola fila. Por eso las columnas se escriben con el nombre de la tabla delante: orders.id, customers.name.
Salen 60 filas, tantas como pedidos: cada pedido tiene exactamente un cliente. Esto se llama JOIN (o INNER JOIN): solo quedan los pares que se encuentran. Teodora y Yavor no están en la lista porque no tienen pedidos. Volveremos a ellos en la próxima lección.
En tablas pequeñas se puede ver cómo ocurre: cuatro pedidos y tres clientes, y Teodora no tiene pedidos.
SELECT orders.id, orders.customer_id, customers.nameFROM ordersJOIN customers ON customers.id = orders.customer_id;Paso a paso, en palabras
- 4 pedidos y 3 clientes. El customer_id del pedido es el id de su cliente.
- El pedido 1 tiene customer_id 2. La base busca al cliente con id 2: Georgi Petrov. El par se convierte en una fila.
- Pedido 2: customer_id 1, es Maria Ivanova.
- El pedido 3 es otra vez del cliente 1: Maria Ivanova está en el resultado por segunda vez.
- El pedido 4 es otra vez del cliente 2: Georgi Petrov está en el resultado por segunda vez.
- Teodora Genova (id 3) no es el customer_id de ningún pedido. No hay par, por eso no está en el resultado.
- 4 filas, tantas como pedidos. JOIN conserva solo los pares que se encuentran.
La misma consulta sobre estas tablas pequeñas. Ejecútala y compárala con el último paso:
La idea
Nombres cortos
orders.ordered_at y customers.name se hacen largos. A una tabla se le puede dar un nombre corto para la consulta: lo escribes después del nombre de la tabla en FROM y en JOIN.
La misma consulta, el mismo resultado. o es orders, c es customers. El nombre corto vale solo dentro de esta consulta. También puedes escribir FROM orders AS o.
Pruébalo
Los pedidos nuevos
Muestra el número de los pedidos nuevos (estado new) con el nombre y el correo del cliente, para poder enviar una confirmación.
Solución
SELECT o.id, c.name, c.email
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'new';FROM orders o JOIN customers c ON c.id = o.customer_id WHERE o.status = 'new'. 11 pedidos. El correo está en customers, así que sin JOIN no hay forma de mostrarlo junto al pedido.
Míralo
«ambiguous column name»
Aquí hay una consulta sin nombres de tabla. Ejecútala:
Tanto orders como customers tienen una columna id. Después de un JOIN las columnas de las dos están juntas, y la base no sabe a qué id te refieres. «Ambiguous» significa ambiguo: se puede leer de dos maneras. La columna name existe solo en customers, así que de esa no se queja.
La solución es decir de qué tabla es la columna:
Una buena costumbre es poner el nombre corto delante de cada columna en una consulta con JOIN, aunque no se exija. Quien la lea ve enseguida de dónde viene cada columna.
La idea
JOIN, WHERE y ORDER BY
Después de un JOIN, todo lo que conoces funciona como antes, y las condiciones pueden usar columnas de las dos tablas. Los pedidos de los clientes de Varna, por fecha:
La ciudad está en customers, la fecha en orders. El orden de las partes es: SELECT … FROM … JOIN … ON … WHERE … ORDER BY.
Pruébalo
Qué hay en el pedido 60
Muestra el nombre del producto, la cantidad y el precio de cada línea del pedido 60.
Solución
SELECT p.name, oi.quantity, oi.unit_price
FROM order_items oi
JOIN products p ON p.id = oi.product_id
WHERE oi.order_id = 60;FROM order_items oi JOIN products p ON p.id = oi.product_id WHERE oi.order_id = 60. Pan blanco, 2 a 1,20 €, y detergente para platos, 4 a 2,90 €. Lo mismo que armamos con los ojos en la lección «La tienda».
Ejercicio
Dos tareas
1. La tienda está investigando por qué se cancelan pedidos. Muestra el número de los pedidos cancelados (cancelled) con el nombre y la ciudad del cliente.
Los pedidos cancelados con el cliente y su ciudad:
Solución
SELECT o.id, c.name, c.city
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'cancelled';JOIN customers c ON c.id = o.customer_id WHERE o.status = 'cancelled'. 7 pedidos. El pedido 19 es de Boris, que no tiene ciudad: el JOIN es por id, así que la ciudad vacía no estorba y sale con NULL.
2. El equipo de calidad quiere las reseñas con puntuación de 3 o menos junto con el nombre del producto, para saber qué revisar.
Las puntuaciones bajas: el producto, la puntuación y el texto de la reseña:
Solución
SELECT p.name, r.rating, r.body
FROM reviews r
JOIN products p ON p.id = r.product_id
WHERE r.rating <= 3;FROM reviews r JOIN products p ON p.id = r.product_id WHERE r.rating <= 3. Cuatro reseñas: del café (1), del detergente en polvo (2), de la sartén (3) y del agua mineral (3).
Más precisamente, para curiosos
También te encontrarás con la forma más antigua: las tablas en FROM separadas por una coma, y la condición para los pares en WHERE.
El resultado es el mismo. La forma JOIN … ON mantiene la condición de unión separada de las condiciones de filtrado. Por eso el curso escribe JOIN.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: WHERE: filtrar filas · NULL: sin valor · ORDER BY, LIMIT y DISTINCT · Clave primaria y clave foránea
- Continúa en: LEFT JOIN: también las filas sin pareja · Muchas tablas, y una tabla unida consigo misma · UNION, INTERSECT, EXCEPT y CROSS JOIN · Subconsultas
- Ejercicios sobre el tema: Unir tablas