重复事件的MySQL模式 - 按特定日期查询

时间:2014-04-13 20:56:23

标签: mysql schema

我即将开始为一个系统制定架构,该架构将有重复发生的事件并继续通过不同的选项。这些都不是理想的。

要求是我需要存储事件及其发生的模式我还需要能够使用特定日期查询此数据,以确定任何这些事件是否涵盖指定的日期/时间。

演示我之后的功能的示例沿着列车时间查找系统工作。

我希望能够插入火车开往特定旅程的时间。星期一 - 星期五每天上午10点说。

然后我希望能够查询这个数据集,看看是否有任何列车在2014年4月30日星期三上午10点(左侧15分钟左右,所以9:45 - 10:15)离开。

我一直在前进和前进,没有取得任何实际进展,所以任何想法都会受到高度赞赏。

2 个答案:

答案 0 :(得分:0)

如果您需要自己代表规则 ......最佳做法是按照自己的逻辑表示数据。所以我会创建表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(在您的情况下可能类似于train 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'

答案 1 :(得分:0)

与@TMS一样,我也会使用Schedule表。我所知道的火车桌不仅在工作日,节假日和银行假日(25.12天或复活节星期一)和季节也有所不同。

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

然后你需要一张桌子CalendarDay,其中包含有趣年份的所有日子,你必须在那里标记假日和银行假日。如果幸运的话,那些人不依赖于您所在国家/地区。在德国,你拥有所有地区(Saxonia与巴伐利亚等不同)。

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

该日历日表也可以标记DST噩梦,例如,较短的一天为-1,较长的一天为+1,正常天为0。这也与Schedule相关,我认为有些列车在DST-switch-days上表现不同,所以逻辑相同:tinyint在较短的一天为“-1”,在较长的一天为“+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表中的限制)。但是当它们已经在表结构中时,更容易对这些“问题”作出反应。