【问题标题】:MySQL schema for recurring events - Query by specific date用于重复事件的 MySQL 模式 - 按特定日期查询
【发布时间】:2014-04-22 01:49:08
【问题描述】:

我即将开始为一个系统构建一个架构,该系统将具有重复性事件并不断经历不同的选择。这些都不理想。

要求是我需要存储事件和它们发生的模式我还需要能够使用特定日期查询此数据,以确定指定的日期/时间是否被这些事件中的任何一个覆盖。

一个演示我所追求的功能的示例,类似于火车时间查询系统。

我希望能够插入火车出发前往特定旅程的时间。比如周一到周五每天上午 10 点。

然后我希望能够查询此数据集,以查看是否有任何火车在 2014 年 4 月 30 日星期三上午 10 点(两边有 15 分钟的余地,因此 9:45 - 10:15)离开。

我一直在这方面来来回回,没有取得任何实际进展,所以任何想法都会非常感激。

【问题讨论】:

    标签: mysql schema


    【解决方案1】:

    和@TMS 一样,我也会使用日程表。我知道的火车表不仅在工作日不同,而且在节假日和银行假日(如 25.12. 或复活节星期一)和季节也不同。

    所以我会将@TMS 的表扩展一列Holiday 和BankHoliday(或者更好的名字,我只是德国人)tinyint,0 = false,1=true,NULL = always。这意味着,如果火车只在节假日来,它在假期列中得到“1”,如果只是在上学时间,它得到“0”,如果节假日无关紧要,它得到 NULL。

    然后您需要一个包含有趣年份的所有日期的 CalendarDay 表,您必须在其中标记假日日和银行假日日。如果幸运的话,这些不取决于您所在国家/地区的地区。在德国,您拥有按地区划分的所有内容(萨克森与巴伐利亚等不同)。

    我确信夏季和冬季有不同的时间表,并且每年都会更改这些时间表(2014 年夏季!= 2013/2014 年冬季!= 2013 年夏季)。所以我会添加另一个带有 ID、名称、起始日期和截止日期的表 ScheduleTable,它的 ScheduleTableID 也是表 Schedule 中的一个额外字段。这意味着,您已经可以存储下一个夏季日程表的日程表。我会将“直到”排他性,因此 2014-04-01 表示“有效期至 2014-03-31”。必要时更容易加入连锁店。

    该日历日表还可以标记 DST 噩梦,例如用 -1 表示较短的一天,+1 表示较长的一天,0 表示正常的日子。这也与时间表有关,我认为有些火车在 DST 切换日的行为不同,所以逻辑相同:在较短的一天中带有“-1”的 tinyint,在较长的一天中带有“+1”,在较长的一天中带有“0”正常天数,如果 DST 对该火车无关紧要,则为 NULL。

    正如 TMS 所说,查询是 BETWEEN <usertime> - interval 15 minute and <usertime> + interval 15 minute,仅针对所有 calendar_day 值进行扩展。

    所以,当用户给出“2014-04-25 16:30”时,你应该像这样查询:

    select Sc.* 
    from Schedule sc
    inner join CalendarDay cd on 
    (
       cd.day = date(<userdate>) 
       and (cd.holiday = sc.holiday or sc.holiday is null) 
       and (cd.BankHoliday = sc.BankHoliday or sc.BankHoliday is null) 
       and (sc.DSTSwitch = cd.DSTSwitch or sc.DSTSwitch is null) 
       and sc.`weekday` = weekday(cd.day)
    )
    inner join ScheduleTable sct on( 
       sct.id = sc.ScheduleTableID 
       and sct.from <= cd.day and sct.until > cd.day
    )
    where sc.`Time` between 
          time(<userdate>) - interval 15 minute 
          and time(<userdate>) + interval 15 minute
    ;
    

    这听起来可能有点复杂,但只要你没有 ScheduleTables 和 Holidays 之类的,这些字段就不会打扰你(将它们设置为 0,将 ScheduleTableID 设置为 1,日期范围从1000 年到 3000 年,NULL 表中的限制)。但是当它们已经在表结构中时,对这些“问题”做出反​​应会更容易。

    【讨论】:

      【解决方案2】:

      如果您需要自己表示规则...最好的做法是按照他们自己的逻辑来表示数据。所以我会创建表Schedule

      Id    EventId    WeekDay    Time
       1          1          0    10:00
       2          1          1    10:00
       3          1          2    10:00
       4          1          3    10:00
       5          1          4    10:00
      

      因此,对于每个 EventId(在您的情况下可能类似于火车 id),您可以有 n 行时间表。诀窍是使用WeekDay 作为weekday() 函数的编码 - Monday = 0, Tuesday = 1, ... Sunday = 6。然后,执行您需要的查询非常简单:

      select distinct EventId
      from Schedule
      where `WeekDay` = weekday('2014-04-30') and `Time` > '9:45' and `Time` < '10:15'
      

      【讨论】:

        猜你喜欢
        • 2011-05-07
        • 2014-07-09
        • 1970-01-01
        • 1970-01-01
        • 2017-05-26
        • 2012-07-26
        • 1970-01-01
        • 2021-11-14
        • 2013-05-25
        相关资源
        最近更新 更多