Соединение трёх таблиц
Для некоторых вопросов нужно больше двух таблиц. Какие игры были в каком заказе и когда этот заказ сделан? Названия лежат в games, даты — в orders, а связывает их order_items: в каждой её строке есть order_id и game_id. Поэтому order_items соединяют с обеими таблицами:
SELECT o.id, o.ordered_at, g.title, i.quantity
FROM order_items AS i
JOIN orders AS o ON i.order_id = o.id
JOIN games AS g ON i.game_id = g.id
ORDER BY o.id, g.title;| id | ordered_at | title | quantity |
|---|---|---|---|
| 1 | 2024-01-20 | Cube Logic | 1 |
| 1 | 2024-01-20 | Moon Farm | 1 |
| 2 | 2024-02-14 | Galaxy Trader | 1 |
| 3 | 2024-02-29 | Ocean Deep | 1 |
| … | … | … | … |
Каждый JOIN добавляет одну таблицу и имеет своё ON. Можно представить, что база данных работает по шагам: первый JOIN сопоставляет каждую позицию с её заказом, и получаются строки со столбцами обеих таблиц; второй JOIN затем добавляет к каждой из этих строк её игру. В итоге каждая строка результата — это одна позиция со столбцами всех трёх таблиц.
order_items стоит посередине и связывает две другие таблицы: в заказе может быть много игр, а игра может входить во многие заказы. Такая связь называется «многие ко многим», и база данных хранит её в таблице между двумя другими — связующей таблице, такой как order_items. Таблица reviews того же рода: она связывает игры с клиентами, которые написали о них отзывы.
И можно идти дальше. У каждого заказа есть customer_id, поэтому четвёртую таблицу — клиентов — к заказам присоединяет ещё одна строка:
JOIN customers AS c ON o.customer_id = c.idВ её ON используется o — таблица, которая уже есть в запросе. Чтобы найти условия, идите по внешним ключам, как вы делали вручную на первом уроке: order_items.order_id → orders.id, orders.customer_id → customers.id, order_items.game_id → games.id. Каждый ключ, по которому вы идёте, — это один JOIN, и яснее всего записывать JOIN в том порядке, в котором вы идёте по ключам.
Типичная ошибка — столбец таблицы, которой нет в запросе. Если написать c.name в SELECT, но забыть соединить customers, получится ошибка no such column: c.name. Псевдоним существует только после того, как таблица соединена.
Задание
- 1
Покажите, кто написал отзыв на какую игру: соедините
reviewsсgamesи сcustomersи покажитеtitleигры,nameклиента иstars. Отсортируйте строки поtitle, затем поname:title name stars Bakery Story Mia Lewis 4 Cube Logic Emma Clark 3 Cube Logic Olivia Brown 5 Dragon Forge Ava Green 3 … … … - 2
Ниже напишите запрос, который показывает, что купил каждый клиент, по четырём таблицам:
nameклиента, дату заказа (ordered_at) иtitleигры. Отсортируйте строки поname, затем поordered_at, затем поtitle:name ordered_at title Ava Green 2024-05-11 Pixel Racer Ava Green 2025-04-15 Dragon Forge Emma Clark 2024-01-20 Cube Logic Emma Clark 2024-01-20 Moon Farm Emma Clark 2024-03-15 Dragon Forge … … …