Почему данные хранятся в разных таблицах
До сих пор каждый запрос читал одну таблицу. Но ответ на обычный вопрос о магазине нередко разбросан по нескольким. Кто сделал заказ 4? Таблица orders знает только идентификатор клиента. А что было в заказе? Это лежит в order_items, и опять только в виде идентификаторов игр. Зачем база данных хранит всё порознь, если из-за этого на такие вопросы труднее отвечать?
Представьте, что магазин хранил бы всё в одной большой таблице: по строке на каждую позицию каждого заказа, и всё о позиции прямо в её строке. Вот как выглядели бы заказы клиентки Emma Clark:
| order_id | name | city | title | price | |
|---|---|---|---|---|---|
| 1 | Emma Clark | emma.clark@mail.com | London | Cube Logic | 5 |
| 1 | Emma Clark | emma.clark@mail.com | London | Moon Farm | 20 |
| 4 | Emma Clark | emma.clark@mail.com | London | Dragon Forge | 40 |
| 14 | Emma Clark | emma.clark@mail.com | London | Ice Hockey Pro | 45 |
| 14 | Emma Clark | emma.clark@mail.com | London | Zombie Town | 30 |
| 26 | Emma Clark | emma.clark@mail.com | London | Knight's Oath | 60 |
Читать такую таблицу легко, но в ней снова и снова повторяется одно и то же. Имя, email и город Emma есть в каждой строке каждого её заказа, а название каждой игры было бы в строке каждого заказа, в который она входила. Из-за этого возникают проблемы:
- Каждое изменение нужно вносить во многих местах. Когда Emma меняет email, его нужно изменить во всех её строках. Пропустите хоть одну — и таблица говорит две разные вещи, а какая из них правда, никто не знает.
- Опечатки разделяют данные. Если в одной строке написано «Emma Clarke», она вдруг выглядит как два разных клиента.
- Некоторым данным некуда деться. У клиента, который ещё ничего не заказал, или у игры, которую никто не купил, не было бы строки.
- Таблица получается слишком большой, потому что один и тот же текст хранится много раз.
Поэтому база данных делит данные на таблицы так, чтобы каждая вещь хранилась ровно один раз: у каждого клиента одна строка в customers, у каждой игры одна строка в games. Как вы видели на первом уроке, у каждой такой строки есть первичный ключ — столбец id с числом, которого нет ни в одной другой строке таблицы. Другие таблицы указывают на строку по этому числу с помощью внешнего ключа: customer_id в orders хранит id клиента, а game_id в order_items — id игры. Когда Emma меняет email, он меняется в одной строке, а все её заказы по-прежнему указывают на неё.
Загвоздка в том, что ответ на один вопрос теперь разбросан по нескольким таблицам. С тем, что вы знаете сейчас, ходить по ключам приходится самим, запрос за запросом. Сначала узнаем, кто сделал заказ 4:
SELECT customer_id
FROM orders
WHERE id = 4;| customer_id |
|---|
| 1 |
Клиент с идентификатором 1. Вы читаете число в результате и используете его во втором запросе:
SELECT name, email
FROM customers
WHERE id = 1;| name | |
|---|---|
| Emma Clark | emma.clark@mail.com |
Это работает, но работа медленная: число пришлось скопировать из одного результата в следующий запрос. Для списка всех тридцати заказов с именами клиентов понадобился бы тридцать один запрос. В следующем упражнении вы поручите это базе данных: соедините таблицы в одном запросе.
Задание
- 1
Кто сделал заказ 13? Напишите запрос, который показывает
customer_idиordered_atзаказа, у которогоidравен 13:customer_id ordered_at 10 2024-12-05 - 2
Ниже добавьте запрос, который показывает
nameиcityклиента с найденным идентификатором:name city Oscar King Bristol - 3
А что он купил? В строках
order_items, гдеorder_idравен 13, хранятся идентификаторы игр. Найдите их на вкладке «Таблицы» или своим запросом. Затем добавьте запрос, который показываетidиtitleэтих игр, отсортированные поid. С помощьюINи списка идентификаторов хватит одного запроса:id title 3 Moon Farm 16 Bakery Story