Что должно содержаться в таблице для связи многие ко многим между заказами и продуктами
Что проверяют
Умеете ли вы спроектировать связующую таблицу и понимаете ли, что в ней лежит не только пара ключей. Для аналитика это ещё и вопрос про зерно таблицы: одна строка тут это одна позиция заказа, и от этого зависят все последующие подсчёты.
Как отвечать
Обязательный минимум это два внешних ключа, на заказ и на продукт. Дальше идёт то, ради чего таблица и заводится:
- количество;
- цена и скидка на момент заказа. Это не дубль справочника, а снимок: цена продукта завтра изменится, а сумма старого заказа меняться не должна;
- порядковый номер позиции, если важен порядок строк в документе;
- служебные метки времени.
create table order_items (
id bigserial primary key,
order_id bigint not null references orders (id),
product_id bigint not null references products (id),
quantity int not null check (quantity > 0),
unit_price numeric(12, 2) not null
);Отдельно проговорите ключ. Составной первичный ключ по паре запрещает две строки с одним продуктом в одном заказе, а это иногда нужно: разная цена, подарочная позиция, разные условия поставки. Поэтому чаще берут суррогатный ключ, а уникальность пары добавляют индексом, если она действительно требуется.
Где спотыкаются
Не сохраняют цену и считают выручку через соединение со справочником продуктов. Отчёт за прошлый месяц начинает меняться после каждого обновления прайса, и сходимость с бухгалтерией пропадает.
Забывают индекс по второму ключу. Составной первичный ключ выручает при выборке по заказу, а запрос «в каких заказах встречался этот продукт» идёт сканированием: нужен отдельный индекс по идентификатору продукта.
Теряют зерно при агрегации. Соединение заказов с позициями размножает строку заказа, и сумма по полю самого заказа, доставке или общей скидке, считается столько раз, сколько в заказе позиций. Суммы по заказу и по позициям считаются отдельно, потом соединяются.