Хранение зависимых дат в SQL - PullRequest
0 голосов
/ 11 сентября 2009

У меня довольно много ситуаций, когда у меня есть структуры баз данных, подобные:

Событие TABLE (EventID INT PrimaryKey, Start DATETIME, Finish DATETIME);и TABLE EventTask (EventTaskID INT PrimaryKey, EventID INT ForeignKey, TaskStart DATETIME, TaskFinish DATETIME)

1 для многих отношений между событиями и EventTasks и т. д.

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

Мне было интересно, может быть лучше заменить TaskStart DATETIME и TaskFinish DATETIMEс двумя INTS: один для смещения Event.Start (мин. отличается от Event.Start) и Duration.

Таким образом, обновления даты становятся намного более надежными, поскольку только одна строка требует обновления.

(я утверждаю, что это применимо только в том случае, если даты EventTask абсолютно зависят от дат событий)

Ответы [ 3 ]

2 голосов
/ 11 сентября 2009

Да, это звучит вполне разумно для меня. Основным недостатком было бы то, что для того, чтобы узнать фактическое время EventTasks, вы должны выполнить вычисления. Это замедлит все, возвращающее время, и, в частности, повредит запросы, включающие времена EventTask в фильтре - например, «найди мне все задачи, которые происходят между временами X и Y.» Те, кто раньше мог использовать индекс, но больше не смогут.

1 голос
/ 11 сентября 2009

Если вы используете SQL 2008, вы можете использовать datetimeoffset тип данных.

Если вы хотите получить «напрямую» данные, без особых хлопот вы можете использовать вычисляемые столбцы , но вы не сможете создать индексы (или заставить их хранить результат) на них если результат недетерминированный.

Ваша структура будет выглядеть так:

TABLE [Event] (
    EventID INT PrimaryKey, 
    Start DATETIME, 
    Finish DATETIME)

TABLE [EventTask](
    EventTaskID INT PrimaryKey, 
    EventID INT ForeignKey, 
    TaskStart DATETIMEOFFSET, 
    TaskFinish DATETIMEOFFSET,
    EventTaskStart as [getStartDateByEvent](eventId, TaskStart) <PERSISTED>,
    EventTaskStop as [getStopDateByEvent](eventId, TaskStart) <PERSISTED>,
    )

FUNCTION [getStartDateByEvent](eventId, TaskStart) as DATETIME
BEGIN
    SELECT [EVENT].start + TaskStart from [EVENT] WHERE [EVENT].EVENTID = eventID
END

FUNCTION [getStartDateByEvent](eventId, TaskStop) as DATETIME
BEGIN
    SELECT [EVENT].[finish] + TaskStop from [EVENT] WHERE [EVENT].EVENTID = eventID
END
0 голосов
/ 19 июля 2010

Джон Скит:

для выполнения расчетов. Что будет замедлить что-либо возвращая раз, а в частности будет больно запросы с участием EventTask раз в фильтр - например, найди мне все задачи которые происходят между временами X и Y. "

Мне кажется, у вас уже есть это требование при написании базовых ограничений целостности данных, например что даты задачи события должны быть в пределах дат для самого события, например расширение вашей схемы в SQL DLL:

CREATE TABLE Event 
(
 EventID INTEGER NOT NULL PRIMARY KEY, 
 event_Start DATETIME NOT NULL, 
 event_Finish DATETIME NOT NULL, 
 CHECK (event_Start < event_Finish), 
 UNIQUE (event_Start, event_Finish, EventID)
)

CREATE TABLE EventTask 
(
 EventTaskID INTEGER NOT NULL PRIMARY KEY, 
 EventID INTEGER NOT NULL, 
 event_Start DATETIME NOT NULL, 
 event_Finish DATETIME NOT NULL, 
 FOREIGN KEY (event_Start, event_Finish, EventID)
    REFERENCES Event (event_Start, event_Finish, EventID)
    ON DELETE CASCADE
    ON UPDATE CASCADE, 
 event_task_START DATETIME NOT NULL, 
 event_task_Finish DATETIME NOT NULL, 
 CHECK (event_task_Start < event_task_Finish), 
 CHECK (event_Start <= event_task_Start), 
 CHECK (event_Finish <= event_task_Finish)
);

Если задачи события являются последовательными, то вам также необходимо написать ограничение для предотвращения перекрывающихся периодов, и это может включать подзапрос (большинство продуктов SQL не поддерживают это ограничение CHECK, например, в SQL Server вам потребуется прибегнуть к курку). Если вам приходилось пересчитывать смещения с использованием временных функций (DATEADD и т. Д.), То производительность могла бы быть проблемой в среде с высокой активностью, не говоря уже о повышенной сложности кода SQL DLL.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...