Урок 5 из 8 · 25 мин · обновлено

Данные: сущности, связи и SQL для аналитика

Как аналитик описывает данные системы: сущности и атрибуты, связи один-ко-многим и многие-ко-многим, ER-диаграмма, и какие SQL-запросы нужны, чтобы проверять данные и отвечать на вопросы бизнеса.

Сущности и атрибуты

Система хранит данные о чём-то: гостях, заказах, напитках, баллах. Каждое такое «что-то» — сущность, а её свойства — атрибуты:

Сущность Атрибуты
Гость id, имя, телефон, баланс баллов, дата регистрации
Заказ id, гость, дата и время, сумма, статус
Напиток id, название, цена, доступен ли сейчас

Для каждого атрибута аналитик уточняет:

  • тип — число, текст, дата, да/нет;
  • обязательность — может ли быть пустым. Телефон гостя — обязателен, имя — можно не указывать;
  • правила — формат телефона, баланс не может быть отрицательным, статус только из списка.

Связи

Сущности связаны между собой:

  • один-ко-многим — у одного гостя много заказов, у заказа один гость. В таблице заказов хранится guest_id — ссылка на гостя;
  • многие-ко-многим — в заказе много напитков, напиток входит во много заказов. Такую связь хранят через промежуточную сущность позиция заказа: заказ, напиток, количество, цена на момент заказа;
  • один-к-одному — встречается реже: например, гость и его настройки уведомлений.

Цену стоит хранить в позиции заказа, а не брать из справочника напитков: если капучино подорожает, старые заказы не должны пересчитаться.

ER-диаграмма

ER-диаграмма (сущность — связь) рисует всё это схемой: прямоугольники-сущности с атрибутами и линии-связи с пометками «1» и «много».

Текст
Гость 1 ──── * Заказ 1 ──── * Позиция заказа * ──── 1 Напиток

По этой схеме разработчики проектируют таблицы базы данных, а аналитик проверяет, что учтены все данные из требований.

SQL для аналитика

Аналитику не нужно проектировать базу как разработчику, но нужно уметь самому проверить данные: сколько гостей с баллами, правильно ли посчитаны суммы, есть ли «сломанные» записи. Для этого нужен SQL — язык запросов к базам данных.

Учебные таблицы guests (гости) и orders (заказы). Гости с баллами по убыванию:

SQL
SELECT name, points
FROM guests
WHERE points > 0
ORDER BY points DESC;
Результат
name  | points
Анна  | 120
Иван  | 40

Сколько заказов и на какую сумму у каждого гостя:

SQL
SELECT g.name, COUNT(o.id) AS orders, SUM(o.total) AS spent
FROM guests g
JOIN orders o ON o.guest_id = g.id
GROUP BY g.name
ORDER BY spent DESC;
Результат
name  | orders | spent
Анна  | 3      | 940
Иван  | 1      | 180

В базе есть ещё гостья Мария без заказов, но её в результате нет: JOIN оставляет только тех, у кого есть пара в другой таблице. Чтобы увидеть всех, нужен LEFT JOIN — он покажет Марию с нулём заказов.

Подробно SQL разобран в курсе «SQL с нуля»: выборки, условия, группировка и соединение таблиц.

Попробуйте сами. Опишите сущность «Начисление баллов» для программы лояльности: атрибуты с типами и обязательностью, связи с другими сущностями. Затем напишите запрос: все гости и количество их заказов, включая гостей без заказов.

Решение

Начисление баллов:

Атрибут Тип Обязательно Правила
id число да уникальный
гость ссылка на «Гость» да
заказ ссылка на «Заказ» да одно начисление на заказ
баллы целое число да больше 0
статус список да ожидает, начислены, отменены, списаны обратно
дата дата и время да

Связи: гость 1 — много начислений; заказ 1 — одно начисление.

SQL
SELECT g.name, COUNT(o.id) AS orders
FROM guests g
LEFT JOIN orders o ON o.guest_id = g.id
GROUP BY g.id, g.name
ORDER BY orders DESC;
Результат
name  | orders
Анна  | 3
Иван  | 1
Мария | 0

COUNT(o.id) считает только найденные заказы, поэтому у Марии 0, а не 1.

Мини-тест: проверьте себя

Закрепите урок: несколько вопросов, разбор ответов — в конце.

  1. У одного гостя может быть много заказов, а у заказа — один гость. Какая это связь?

  2. Заказ может содержать много напитков, а напиток — входить во много заказов. Как это хранят?

  3. Чем LEFT JOIN отличается от JOIN в запросе «гости и число их заказов»?