Как хранить в базе данных даты и сроки возникновения событий для быстрых и элегантных запросов? - PullRequest
7 голосов
/ 14 января 2012

Допустим, я веду базу данных событий, которая может быть любой, начиная от еженедельного графика рабочего времени компании (понедельник-пятница: 10:00 - 7:00, суббота: 12:00 - 18:00, вс: выходной) до ежемесячных событий (Ярмарка произведений искусства, каждую первую субботу, с 10:00 до 17:00) до ежегодного мероприятия (благотворительный ужин в сочельник, 19:00 - 21:00)

В идеальной ситуации я хотел бы запросить базу данных в любой день, скажем: Четверг, 12 января 2012 г., 12:00

... и найдите все события, происходящие в:

  • полдень четверга (например,бизнес открыт) * ​​1010 *
  • каждый второй четверг (художественная ярмарка)
  • янв.12, а именно (э-э ... День памяти Туркменистана)

Полагаю, нет смысла говорить о построении запроса, не подумав сначала, как такие даты / время будут храниться в базе данных.

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

  • Время начала
  • Продолжительность
  • День недели (например, пн. Вт.. и т. д.)
  • необязательная абсолютная годовая дата (например, 8 мая)
  • необязательное ежемесячное вхождение (четвертая среда)

И я предполагаю, что нет никакого способаинкапсулируйте это в один ряд, верно?Например, бизнес, открытый каждый будний день, будет иметь пять записей.

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

Ответы [ 2 ]

3 голосов
/ 15 января 2012

Не уверен, что если вы специально запрашиваете решение, не зависящее от dbms, в любом случае в postgresql (и я думаю, что это возможно в большинстве RDBMS), вы можете хранить метки времени и получать из них много информации: http://www.postgresql.org/docs/8.4/interactive/functions-datetime.html.

Postgresql-специфичный ответ

9.9.1. ВЫПИСКА, дата_часть

EXTRACT (поле FROM source) Функция извлечения извлекает подполя например, год или час из значений даты / времени. источник должен быть значением выражение типа timestamp, time или interval. (Выражения типа дата приведена к метке времени и поэтому может использоваться также.) поле является идентификатором или строкой, которая выбирает, какое поле извлечь из исходное значение. Функция extract возвращает значения типа double точность. Ниже приведены допустимые имена полей: [...] день, DOW (день недели), DOY (день года), [...]

Так, например, чтобы выбрать события, происходящие каждый второй четверг, вы можете написать:

SELECT * FROM events  #your table
    WHERE EXTRACT(DOW FROM date_column)=4 # DOW  goes from sunday (0) to saturday (6)
    AND EXTRACT(DAY FROM date_column)>7 # must occurr after 7th day of the month (ie. if the 1st is a Thursday
    AND EXTRACT(DAY FROM date_column)<15 # and before the 15th (ie. if the 1st is a Friday, so the first Thursday is on the 7th, and the second is on the 14th)

Для моделирования продолжительности вы можете просто иметь 2 поля отметок времени для начала / конца события.

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

В целом , я сначала попытался бы использовать типы данных и функции, предоставляемые вашей СУБД, и только если вы не можете найти решение, попробуйте смоделировать его самостоятельно.

2 голосов
/ 15 января 2012

если вы поддерживаете следующее время начала / окончания для каждого события, тогда запрос прост: выберите все события, где время начала <= отметка времени <время окончания. </p>

Эффективное ведение такой таблицы зависит от вашего приложения,Посмотрите, как реализованы существующие приложения, похожие на calendar / todo / cron.Например, вы можете обновлять все события, у которых есть время окончания в прошлом, периодически или перед каждым запросом.

Преимущество этого подхода состоит в том, что вы можете использовать произвольную сложную логику для вычисления следующего времени начала / окончания..

И я предполагаю, что нет способа инкапсулировать это в одну строку, верно?

Вы можете хранить одно поле: "Правило", которое описывает вcrontab-подобный язык при возникновении события ( пример: разобрать запись crontab, вычислить время следующего запуска ).

...