#database #database-design #calendar
#База данных #база данных-дизайн #Календарь
Вопрос:
Сайт посвящен специальным событиям со скидками. Каждое событие содержит период времени (точнее, даты), в течение которого оно является действительным. Однако часто возникает ограничение, заключающееся в том, что сделка недействительна, скажем, по субботам и воскресеньям (или даже в определенный день).
В настоящее время мой грубый дизайн состоял бы в том, чтобы иметь две таблицы:
В таблице событий хранятся идентификатор события, дата начала и окончания продолжительности и все другие вещи.
В таблице EventInvalidDate хранится идентификатор события и конкретные даты, по которым сделки недействительны. Для этого требуется, чтобы код приложения заранее вычислял недопустимые даты.
Кто-нибудь знает лучший шаблон, соответствующий этому требованию, или возможную ошибку для моего дизайна? Это требование похоже на подмножество общей модели календаря, поскольку оно не требует бесконечного повторения событий в будущем (т. Е. Каждое событие имеет определенную продолжительность).
Обновить
Мой коллега предложил создать таблицу периодов с датами начала и окончания. Если период находится между 1 января и 7 января, при этом 3 января является исключением, в таблице будет записано: 1 января ~ 2 января, 4 января ~ 7 января.
Кто-нибудь знает, лучше ли это так же, как подход ответа, с точки зрения производительности SQL. Спасибо
Ответ №1:
Указание того, какие даты не включены, может уменьшить количество строк базы данных, но это усложняет вычисления, запросы и отчеты.
Я бы перевернул ее с ног на голову.
-
Есть главная
Event
таблица, в которой перечислены первая и последняя дата события. -
Также есть подробная
EventDates
таблица, которая заполняется всеми датами, когда доступно событие.
Использование этого подхода упрощает работу, особенно при написании запросов и отчетов.
Обновить
Наличие строки на дату позволяет выполнять точные соединения по датам с другими таблицами и позволяет агрегировать данные за день для целей отчетности.
select ...
from sales
inner join eventDates
on sales.saleDate = eventDates.date
Если в вашей таблице EventDates используются даты начала и окончания, создавать соединения становится сложнее:
select ...
from sales
inner join eventDates
on sales.saleDate >= eventDates.start and sales.SaleDate < eventDates.finish
Соединения с точным совпадением определенно выполняются по индексу, если таковые имеются, в каждой RDBMS, которую я проверил; диапазон совпадает, как и во втором примере, я не уверен. Вероятно, с точки зрения производительности с ними все в порядке, если только в итоге вы не получите метрическую тонну данных.