Algorithm 在数据库中,如何存储事件发生日期和时间范围以进行快速/优雅的查询?

Algorithm 在数据库中,如何存储事件发生日期和时间范围以进行快速/优雅的查询?,algorithm,database-design,datetime,language-agnostic,Algorithm,Database Design,Datetime,Language Agnostic,比如说,我正在维护一个活动数据库,它可以是企业每周营业时间安排的任何内容,周一至周五:上午10点至下午7点,周六:下午12点至下午6点,周日:每月活动艺术博览会关闭,每个第一个周六,从上午10点至下午5点,到一年一度的活动圣诞夜慈善晚宴,晚上7点至9点 在理想情况下,我希望查询任意给定日期的数据库,例如: 2012年1月12日星期四下午12点 …并查找在上发生的所有事件: 正常的星期四中午,如营业时间 每隔一个星期四就有一次艺术博览会 1月12日,特别是呃…土库曼斯坦阵亡将士纪念日 我想,如果不

比如说,我正在维护一个活动数据库,它可以是企业每周营业时间安排的任何内容,周一至周五:上午10点至下午7点,周六:下午12点至下午6点,周日:每月活动艺术博览会关闭,每个第一个周六,从上午10点至下午5点,到一年一度的活动圣诞夜慈善晚宴,晚上7点至9点

在理想情况下,我希望查询任意给定日期的数据库,例如: 2012年1月12日星期四下午12点

…并查找在上发生的所有事件:

正常的星期四中午,如营业时间 每隔一个星期四就有一次艺术博览会 1月12日,特别是呃…土库曼斯坦阵亡将士纪念日 我想,如果不先考虑如何将这些日期/时间存储在数据库中,那么讨论查询构造就没有意义了

我想不出,即使忽略边缘情况,每周正常工作时间的概念如何可以在一个记录中建模,一个字段也可以建模每年一次的事件。至少,我需要至少五个字段:

开始时间 期间 一周中的某一天,例如周一。星期二等 可选的绝对年度日期,例如5月8日 可选每月第四个星期三 我猜没有办法把它封装在一行中,对吗?例如,每个工作日营业的企业将有五条记录


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

不确定您是否特别要求dbms不可知解决方案,无论如何,在postgresql中,我认为在大多数RDBMS中都有可能存储时间戳,并从中获取大量信息:

Postgresql特定答案

9.9.1。摘录,日期

EXTRACTfield从源提取函数检索子字段 例如从日期/时间算起的年或小时值。源必须是一个值 时间戳、时间或间隔类型的表达式。类型表达式 日期转换为时间戳,因此也可以使用。领域 是一个标识符或字符串,用于选择要从 源值。extract函数返回double类型的值 精确以下是有效的字段名称:[……]天、道琼斯指数周内日、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个时间戳字段

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


一般来说,我会首先尝试使用DBMS提供的数据类型和函数,只有当您无法真正找到解决方案时,才尝试自己建模。

如果您为每个事件保留下一个开始/结束时间,那么查询很简单:选择所有事件,其中开始时间要求将所有事件存储到一个表中?不一定。我现在在想,将日常事务(如正常工作时间)保存在一个单独的表中,并带有单独的字段,这样做更有意义。我一直希望所有这些问题都有一个逐位解决方案this@Zando:按位解决方案是可能的,例如,但您不应该需要它:范围查询对于索引边界或R*Tree index.OpenTSDB是否可以有效地进行OlogN?或者你是在寻找像Cron这样的东西所使用的日历队列吗?很感谢你给了我一些关于如何建模1/2/3/4(每月)问题的想法。我将考虑如何将其应用到一个查询中,其中有一个给定的日期,并查看哪些事件将该日期包含在其时间范围内。例如,1月12日应该包括所有的第二个星期四。活动,以及每周周四。事件,以及仅在1月12日发生的任何事件