2012-01-14 53 views
7

比方说,我维护着一个事件数据库,这个数据库可以是企业每周工作时间(星期一至星期五:上午10点至下午7点,星期六:下午12点至下午6点,星期日:休息)每月事件(艺术公平,每月第一个星期六,上午10点 - 下午5点),以每年一度的盛事(圣诞夜慈善晚宴,7 PM-9PM)在数据库中,如何存储快速/优雅查询的事件发生日期和时间范围?

在理想情况下,我愿与任何一天来查询数据库,说: 周四,2012年1月12日,中午12时

...,发现都在发生的所有事件:

  • 经常中午周四(如业务是开放的)
  • 每月第二个星期四(艺术博览会)
  • 1月12日,具体为(呃......土库曼斯坦纪念日)

我猜想没有先考虑如何将这样的日期/时间存储在数据库中,谈论查询构造就毫无意义。

我无法想象每周正常运行时间的概念(即使忽略边缘情况)可以用一个单一记录的单个字段进行建模,该字段还将建立一年一度的事件模型。最起码,好像我至少需要五个领域:

  • 启动时间
  • 时间
  • 日的一周内(如星期一星期二等)
  • 可选绝对每年的日期(例如5月8日)
  • 可选每月发生(第四星期三)

而且我猜有没有办法在单排封装,对吗?例如,每个工作日开放的业务将有五个记录。

而最终目标是能够做一个相对优雅的查询,可以查找包含其时间范围内给定时刻的所有事件记录。

+0

是否需要将所有事件存储到一个表中? – Rogach 2012-01-14 18:00:40

+0

不一定。我现在在想,把常规工作如常规工作时间放在一个单独的表格中,并使用单独的字段更有意义。我抱着希望,有一个按位解决所有这些问题 – Zando 2012-01-14 20:02:14

+0

@Zando:按位解决方案是可能的,例如['cron.c'](http://opensource.apple.com/source/cron/cron-2 /cron/cron.c),但你不需要它:范围查询可以是有效的(对于索引边界或R *树索引,O(log(N)) – jfs 2012-01-15 01:56:02

回答

3

不知道你是否特别要求dbms-agnostic解决方案,无论如何在postgresql中(我认为在大多数RDBMS中是可能的),你可以存储时间戳并从中获取大量信息:http://www.postgresql.org/docs/8.4/interactive/functions-datetime.html

PostgreSQL特有的答案

9.9.1。 EXTRACT,date_part

EXTRACT(field FROM source)提取函数从日期/时间值中检索诸如年或小时的子字段 。源必须是值为 表达式类型的时间戳,时间或间隔。 (类型为 的表达式被转换为时间戳,因此也可以使用。)字段 是一个标识符或字符串,用于选择要从 源值中提取的字段。提取函数返回精度类型为double的数值。以下是有效的字段名称:[...]天,DOW(星期),DOY(年的一天),[...]

因此,举例来说,选择每个第2个星期四发生的事件,你可以写:

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个时间戳字段,用于事件的开始/结束。

另请注意,您可以添加或减去时间戳,以及知道间隔是否重叠。

一般,我会先尝试使用您的DBMS提供的数据类型和功能,只有当你真的不能找到一个解决方案试图自行建模。

+0

很荣幸能给你提供一些关于如何模拟“第一/第二/第三/第四[本月]”问题的想法,我将考虑如何将它应用于例如,1月12日应该包括所有第二个周四事件,以及周四周四事件,以及任何只发生在一天中的事件1月12日 – Zando 2012-01-14 22:54:08

2

如果您保留每个事件的下一个开始/结束时间,那么查询很简单:选择开始时间为< =时间戳<结束时间的所有事件。

如何有效维护此类表取决于您的应用程序。查看现有的日历/ todo/cron类应用程序是如何实现的。例如,您可以定期或在每个查询之前更新所有结束时间为过去的事件。

这种方法的优点是您可以使用任意复杂的逻辑来计算下一个开始/结束时间。

而且我猜测没有办法将它封装在一行中,对吗?

您可以存储单个字段:“规则”,在事件发生时以类似crontab的语言描述(example: parse crontab entry, calculate next start time)。

相关问题