Ответ вслух Senior ER-модели и нормализация обновлено

Кейс: история цен тарифов

Вопрос

Оператор связи меняет цены тарифов несколько раз в год. Нужно корректно выставлять счета задним числом и показывать абоненту, по какой цене он платил в каждом месяце. Как смоделируешь?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Цену выношу из тарифа в отдельную таблицу tariffprices с периодом действия: validfrom включительно и validto исключительно, у текущей validto пустой. Для одного тарифа периоды не должны пересекаться, в PostgreSQL это делается ограничением исключения по диапазону.

Что должно прозвучать в ответе

  • Цена не атрибут тарифа, а отдельная сущность с периодом действия (valid_from, valid_to)

  • Запрет пересекающихся периодов для одного тарифа (exclusion constraint или проверка)

  • Подключение абонента к тарифу тоже с периодом

  • Счёт фиксирует цену как снимок на момент начисления

  • Время с часовым поясом, правила для границ периода

Что могут спросить следом

  • Как найти цену на конкретную дату одним запросом?
  • Что если цену изменили задним числом?

Разбор

Цену выношу из тарифа в отдельную таблицу tariff_prices с периодом действия: valid_from включительно и valid_to исключительно, у текущей valid_to пустой. Для одного тарифа периоды не должны пересекаться, в PostgreSQL это делается ограничением исключения по диапазону. Подключения абонентов к тарифам тоже храню с периодами, так видно, кто на чём сидел в каждом месяце. При начислении счёт сохраняет цену и период как снимок, чтобы пересмотр прайса не менял выставленные счета. Изменение задним числом оформляется корректирующим начислением, а не правкой старого счёта. Цена на дату находится условием valid_from <= дата и (valid_to > дата или valid_to пустой).

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.