В отчёте нужно сравнить продажи по дате заказа и отгрузки. Как спроектировать календарь, чтобы фильтр по периоду не давал неоднозначный результат?
Для разных смысловых ролей даты следует использовать отдельные логические представления календаря: например, Календарь заказа и Календарь отгрузки. Каждое представление должно иметь однозначную связь с соответствующим полем факта. Один общий календарь с несколькими активными связями создаёт неоднозначность: один фильтр по периоду может одновременно трактоваться как дата заказа и дата отгрузки.
В аналитических моделях одна таблица фактов часто содержит несколько дат: заказа, оплаты, отгрузки или доставки. При использовании звёздной схемы календарь выступает общей измерительной таблицей, но одна и та же дата может играть разные бизнес-роли.
Подход с отдельными ролевыми представлениями календаря появился как решение проблемы неоднозначной фильтрации. Он делает смысл фильтра явным и позволяет пользователю одновременно анализировать разные даты без скрытого переключения логики.
Предположим, факт продаж содержит дата заказа и дата отгрузки, а модель подключена к одному календарю. Если обе связи активны или механизм выбора связи неочевиден, фильтр «январь» может ограничить строки по одной дате, другой дате или их пересечению — в зависимости от конкретной реализации модели.
Ошибочный результат обычно выглядит правдоподобно: число продаж не обязательно становится нулевым или явно аномальным. Поэтому пользователь может принять показатель по дате заказа за показатель по дате отгрузки и сделать неверные выводы о сроках исполнения заказов.
В модели создают две роли одного календаря: Календарь заказа связан с полем даты заказа, а Календарь отгрузки — с полем даты отгрузки. Их атрибуты должны быть согласованы: год, месяц, неделя и другие периоды должны одинаково определяться, если бизнес не требует разных календарных правил.
Такой вариант особенно надёжен, когда на одном экране одновременно нужны два независимых фильтра: период заказов и период отгрузок. Пользователь понимает, какой временной контекст применён к каждому показателю, а модель не зависит от неявного выбора активной связи.
Другой вариант — один физический календарь с несколькими связями и явным переключением роли даты в расчёте. Он уменьшает дублирование объектов модели, но усложняет семантический слой: разработчик должен гарантировать, что каждый показатель использует правильную связь, а интерфейс должен объяснять текущую роль даты.
Главный компромисс — между компактностью модели и прозрачностью. Отдельные ролевые календари обычно понятнее для самообслуживания и безопаснее при независимой фильтрации, но увеличивают число объектов модели. Какой бы вариант ни был выбран, необходимо проверить фильтры, итоги на контрольном наборе данных и названия показателей: «выручка по дате заказа» и «выручка по дате отгрузки» нельзя оставлять без уточнения.
В компании показатель исполнения заказов сравнивали по месяцу создания заказа, а фактическую отгрузку — по месяцу отгрузки. Сначала использовали один календарь и переключали связь внутри отдельных расчётов. Это экономило место в модели, но часть отчётов применяла календарь заказа к обоим показателям, поэтому задержки отгрузки систематически занижались.
Рассматривались два варианта. Явное переключение связей сохраняло компактную модель, но требовало строгого контроля каждого расчёта. Два ролевых календаря увеличивали модель, зато делали независимые фильтры и названия показателей однозначными.
Выбрали второй вариант: показатели переименовали с указанием роли даты, а тесты сверяли результаты отдельно по дате заказа и отгрузки. После этого пользователи смогли видеть, сколько заказов создано в периоде и сколько из них отгружено в другом периоде, без риска смешать временные контексты.
Обычно это приводит к неоднозначному распространению фильтра. Строка факта должна одновременно соответствовать выбранным значениям по дате заказа и дате отгрузки, поэтому результат может стать пересечением двух условий, а не анализом одной выбранной роли. Без явной семантики такой дизайн трудно проверять и объяснять.
Название не устраняет неоднозначность модели. Пользователь может выбрать месяц, но не понять, к какой дате относится фильтр, а разные визуализации могут использовать разные связи. Если роли действительно независимы, отдельные календарные представления лучше отражают бизнес-смысл и снижают риск неправильной интерпретации.
Нет, логически отдельные роли не обязательно означают копирование исходных строк в базе данных. Их можно реализовать как отдельные представления или объекты семантической модели поверх общего календаря, если используемая BI-платформа это поддерживает. Важен не способ хранения, а однозначная связь каждой роли с нужным полем факта и понятное поведение фильтров.