【问题标题】:How should I (how would you) save schedules in database我应该如何(你将如何)在数据库中保存日程安排
【发布时间】:2011-03-16 16:37:03
【问题描述】:

我有一个应用程序,用户可以在其中为特定日期范围内的特定实体设置时间表。日程编辑类似于输入日历约会:

  • 开始时间和结束时间(小时)
  • 开始日期并设置每周重复日期(即每周六和周日或仅每周一)
  • 重复结束日期 - 设置重复结束的日期

示例

我想将 2011 年 1 月的周末日程安排为早上 7 点到下午 5 点。

  1. 我将开始日期设置为 1.1.2011
  2. 将结束日期设置为 31.1.2011
  3. 我设置在 7:00 开始,在 17:00 结束
  4. 在每周重复掩码中启用星期一

然后我还会输入一个与现有时间表重叠但仅针对 1 月上半月的新时间表:

  1. 设置开始日期 1.1.2011
  2. 设置结束日期 14.1.2011
  3. 设置时间从 9:00 到 15:00
  4. 启用星期一。

问题

我可以将每天的时间表存储在如下表格中:

create table EntitySchedule (
    EntityID int not null
        references Entity(EntityID),
    ForDay date not null,
    StartAt time not null,
    EndAt time not null
)

但是我会在这个表中得到很多记录:

每个计划的记录数 =(实体记录数)*(计划范围内的天数)

或者我可以存储类似于输入数据的数据:

create table EntitySchedule (
    EntityID int not null
        references Entity(EntityID),
    StartRange date not null,
    EndRange date not null,
    StartAt time not null,
    EndAt time not null,
    WeekdayMask tinyint not null -- bitmask of days (7 bits)
        default (0)
)

这张表的记录会比前一张少很多。

比较

它们中的每一个(按日表和按时间表)都有其优点和缺点:

  1. 每天的表格很容易获得特定日期的时间表
  2. 每日计划无法编辑重复数据,您总是会输入一个覆盖现有数据的新计划
  3. 几年后,每天的表将有大量记录,必须加以缓解
  4. 如果按计划表在不计算的情况下获取特定日期的计划是不可能的
  5. 按计划表允许将计划从一个日期范围复制到另一个日期范围,这将是一项非常受欢迎的功能,只需从不同的日期范围导入计划数据并将其应用于新的日期范围,即可轻松创建计划。

使用场景

不要将此视为我们从个人日历中得知的常规日历约会。而是将其视为非常灵活的商店/商店(实体)营业时间(时间表)。因此,我的数据库将包含许多商店,并且它们的营业时间非常灵活,通常每周重复一次。

编辑时间表通常会覆盖现有数据,因此当定义日期范围内的营业时间已经存在时,我们不会真正更新现有时间表定义,而是创建一个新的时间表定义来覆盖现有数据。如果有每天的时间表,这非常简单。我将覆盖适用于新计划日期范围的那些日子。

但在按计划表的情况下,这变得更加复杂:

  1. 我可以在表中插入一条新记录,然后在读取特定日期的时间表时最新记录获胜(一种 LIFO 方法)。这意味着每个计划读取(选择)都将包含一个更复杂的查询,我必须返回与特定实体相关的所有记录,这些记录在正确范围内定义日期,然后返回最后一个。这对于获取特定日期的日程安排很好,但是当我想要某个日期范围的日程安排时,我的生活会很艰难......
  2. 定义的计划范围不重叠,我何时插入新的计划范围也可能意味着应该更改现有计划定义(或其中许多),甚至将其拆分为两个。

第一个似乎是更好的方法。但是查询获取日期范围的时间表变得相当复杂并且可能不是很快。想象一下获取 2011 年 1 月的实体计划。读取数据应始终以每日表的形式产生结果。

问题

是否有任何标准方法来保存计划数据?您建议我如何保存这些数据?

【问题讨论】:

    标签: tsql scheduling sql-server-2008-r2


    【解决方案1】:

    我不知道存储日程数据的任何标准方式。

    我会采用您的第二种方法 - 存储创建计划所需的数据,因为这是用户定义的(例如,考虑如何从“每天”表中加载,以便允许用户编辑他们的日程安排——这会很棘手!)。

    我会在上面的表格中添加一个“上次运行”字段,然后根据您将如何使用它,一个“下次运行”Computed Column 将使用该行中的其他信息来计算下次该预定事件应发生时。这将允许您从数据库中“获取今天发生的所有事件”。

    编辑:现在你已经澄清了关于营业时间的问题(你需要能够列出未来发生的时间表)而不是我假设的对于任务计划程序,您只需要“下一次运行”时间,“下一次运行”字段就没那么有用了。

    但是,我仍然会存储计划数据,因为这实际上是商店将定义的(他们会说“我们希望在工作日 9 点到 5 点之间营业”,而不是“我们”下周一、周二、周三、周四、周五开 9-5 点,然后是下周一....")。虽然我很欣赏它使一些事情变得更复杂,但存储它并导出实际的日常数据会更准确。您仍然可以使用存储过程或基于表的用户定义函数,以便能够选择日常数据。这将再次取决于您的使用场景 - 您是否只想列出每个商店的营业时间,还是想要“获取所有在 XX 开放的商店”的功能?

    【讨论】:

    • 请阅读使用场景部分中的其他信息,因为我仍然不愿意采用按计划的方法。
    • 你能不能再写一些来解释LastRun/NextRun的功能?正如您所描述的那样,NextRun 应该返回许多日期,因此特定日期的匹配实际上会起作用。我可能不完全理解这个想法,所以请你再详细说明一下。
    • LastRun/NextRun 字段在您提到这不是用于存储事件,而是用于开放时间之前就已存在。将其视为 Windows 任务调度程序,其中 Last Run + Schedule Data = Next Run 的组合,这是您在此类系统中唯一需要的重要字段。既然您已经澄清这是关于商店营业时间的,这可能需要一些修改
    • 我将有一个管理屏幕,其中将以图形方式显示特定日期范围内的所有商店和所有营业时间。我永远不会有想要列出在 X 天 Y 小时营业的商店的情况。在返回大量计算数据方面,管理屏幕是最复杂的。在 99% 的其他情况下,我只会在特定日期查询特定商店的数据库。这几乎是微不足道的。
    【解决方案2】:

    我曾多次与这个问题作斗争。我认为最好的方法是简单地将开始日期/时间和结束日期/时间存储为开始和结束的单个字段,或者作为您建议的日期和单独的时间字段。

    我认为这是最灵活的,虽然它需要在您的应用程序层进行更多计算以处理重叠计划等,但它是所有替代方案中“最不差的”。不过,我不确定它是否是标准方式。

    ps。我曾经实现过一个系统,其中一年中的每一天都有一个表格记录,一个单独的表格存储当天使用的所有时间表,但它变得比它的价值更麻烦,因为它还需要在应用程序层进行大量编码,但在不同的地方。我认为使用日期/时间是最好的解决方案。

    【讨论】:

    • 请阅读使用场景部分中的其他信息,因为我仍然不愿意采用按计划的方法。而且由于您以前有过经验,这可能很容易与您过去遇到的特定问题相关。
    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 2015-08-20
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 2015-03-16
    相关资源
    最近更新 更多