【问题标题】:In a database, how to store event occurrence dates and timeframes for fast/elegant querying?在数据库中,如何存储事件发生日期和时间范围以进行快速/优雅的查询?
【发布时间】:2012-01-14 16:23:37
【问题描述】:

假设我正在维护一个事件数据库,它可以是从企业营业时间(周一至周五:上午 10 点至晚上 7 点,周六:12 点至下午 6 点,周日:休息)的每周计划到每月的活动(艺术博览会,每个第一个星期六,上午 10 点至下午 5 点)到年度活动(平安夜慈善晚宴,晚上 7 点至晚上 9 点)

在理想情况下,我想查询任何一天的数据库,比如: 2012 年 1 月 12 日星期四下午 12 点

...并找到所有发生的事件:

  • 一个常规的星期四中午(例如营业中)
  • 每个第二个星期四(艺术博览会)
  • 一月。 12,特别是(呃......土库曼斯坦阵亡将士纪念日)

如果不首先考虑如何将此类日期/时间存储在数据库中,我想讨论查询构造是没有意义的。

我无法想象如何在一个记录单一的字段中建模每周定期工作时间(即使忽略极端情况)的概念,该字段也可以建模每年一次的事件。至少,我似乎至少需要五个字段:

  • 开始时间
  • 持续时间
  • 星期几(例如周一、周二等)
  • 可选的绝对年度日期(例如 5 月 8 日)
  • 可选的每月发生(第四个星期三)

而且我猜没有办法将它封装在一行中,对吧?例如,每个工作日营业的企业将有 5 条记录。

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

【问题讨论】:

  • 是否需要将所有事件存储到一个表中?
  • 不一定。我现在在想,将日常事务(例如正常营业时间)保存在单独的表格中并具有单独的字段更有意义。我一直希望有一个按位解决所有这些问题
  • @Zando:按位解决方案是可能的,例如,cron.c,但您不应该需要它:范围查询可以是高效的(O(log(N) 用于索引边界或 R*Tree 索引)。
  • OpenTSDB?还是您正在寻找更多类似 Cron 之类的东西使用的日历队列之类的东西?

标签: algorithm database-design datetime language-agnostic


【解决方案1】:

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

Postgresql 特定答案

9.9.1。提取,日期部分

EXTRACT(field FROM source) 提取函数检索子字段 例如日期/时间值的年份或小时。来源必须是一个值 时间戳、时间或间隔类型的表达式。 (类型的表达 日期被转换为时间戳,因此也可以使用。)字段 是一个标识符或字符串,用于选择要从 源值。 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 个时间戳字段,用于事件的开始/结束。

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

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

【讨论】:

  • 感谢您为我提供了一些关于如何模拟“1st/2nd/3rd/4th [of the month]”问题的想法。我将考虑如何将其应用于有给定日期的查询,并查看哪些事件在其时间范围内包括这一天。例如,1 月 12 日应包括所有第二个星期四。活动,以及每周四。事件,以及仅在 1 月 12 日发生的任何事件
【解决方案2】:

如果您为每个事件维护下一个开始/结束时间,那么查询很简单:选择开始时间

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-02
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 2012-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多