2014-04-13 98 views
2

我即将开始为系统创建一个模式,该模式将具有重复性事件并继续执行不同的选项。没有一个看起来很理想。重复事件的MySQL模式 - 按特定日期查询

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

一个例子演示了我在沿着火车时间查找系统行后的功能。

我希望能够插入列车在特定旅程中出发的时间。周一至周五,每天早上10点说 - 周五。

然后我想能够查询这个数据集,看是否有列车上午10时离开(15分钟余地任一侧9:45 - 10:15)周三4月30日2014年

我一直往前走,没有任何真正的进展,所以任何想法将不胜感激。

回答

0

像@TMS,我也会使用Schedule表。我所知道的火车表不仅在平日有所不同,而且在假期和银行假期(如25.12或复活节星期一的日子)也不同。

因此,我会通过列Holiday和BankHoliday(或更好的名称,我只是德语)tinyint,0 = false,1 = true,NULL = always来扩展@ TMS的表格。这意味着,如果一列火车只在假期出现,假期中它会得到一个“1”,如果只在学校时间,它会得到一个“0”,如果假期不重要,它会变为NULL。

然后,你需要一个表CalendarDay与有趣的岁月的所有日子,你必须标记假日和银行假日。如果幸运的话,那些依赖于你所在国家的地区。在德国,你有所有区域(萨克森与巴伐利亚等不同)。

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

那个日历表也可以标记DST-nightmare,例如对于较短的日期为-1,对于较长的日期为+1,对于正常日期为0。这在Schedule中也是相关的,我认为有些列车在DST-switch-days上的行为不同,所以同样的逻辑:tinyint在较短的日期为“-1”,在较长的日期为“+1”,在正常日期,如果DST对该列车无关紧要,则为NULL。

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

所以,当用户给出了“2014年4月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假期等等,这些字段不会让你失望(将它们设置为0,将ScheduleTableID设置为1,日期范围从1000年到3000年,将NULL限制在Schedule中)。但是,当他们处于桌面结构中时,对这些“问题”做出反​​应会更容易。

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(这可能是你的情况有点像火车ID),你可以有n个时间表行。诀窍是使用WeekDayweekday()功能的编码 - 星期一= 0,周二= 1,...星期日= 6之后,在执行您需要的查询非常简单:

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