2015-09-19 28 views
0

我正在創建一個程序,其中主要功能是事件日曆。數據庫中有人員和事件,並跟蹤參加個別事件。使用重複間隔生成日期列表

在事件方面,我希望能夠提供重複生成事件的選項。如果事件被重複,用戶提供了以下信息:

1)事件的開始日期 2)活動的結束日期 3)重複天數(例如,四) 4)重複間隔(每週,雙週,和每月)

所有這些信息被插入到一個表,「事件」,然後導致觸發器執行。觸發器使用此信息在另一個表「event_instances」中生成記錄,該表包含給定事件(事件發生的每一天)的每個實例的記錄。然後根據每個實例跟蹤事件出席情況。

爲了最大限度提高性能,我一直在創建一個臨時表的方法,將其過濾爲只有我需要的日期,然後將其插入到event_instance表中。這是一個很好的方法,因爲它能夠在1-2秒內完成整個操作。

我的問題現在歸結爲重複間隔。在我去那裏之前,這裏是我用來生成臨時表的sql代碼。此公式會在@start_date和@end_date之間創建一個包含100,000個日期的表格。 @start_date和@end_date是臨時值,在最後的實現中,這將是一個帶有兩個日期參數的函數。

set @start_date = '2015-9-20'; 
set @end_date = '2016-1-17'; 

select * from 
(select @start_date + interval ((a.a) + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) day this_date 
from 
(select 0 as a 
union all select 1 
union all select 2 
union all select 3 
union all select 4 
union all select 5 
union all select 6 
union all select 7 
union all select 8 
union all select 9) as a 
join 
(select 0 as a 
union all select 1 
union all select 2 
union all select 3 
union all select 4 
union all select 5 
union all select 6 
union all select 7 
union all select 8 
union all select 9) as b 
join 
(select 0 as a 
union all select 1 
union all select 2 
union all select 3 
union all select 4 
union all select 5 
union all select 6 
union all select 7 
union all select 8 
union all select 9) as c 
join 
(select 0 as a 
union all select 1 
union all select 2 
union all select 3 
union all select 4 
union all select 5 
union all select 6 
union all select 7 
union all select 8 
union all select 9) as d 
join 
(select 0 as a 
union all select 1 
union all select 2 
union all select 3 
union all select 4 
union all select 5 
union all select 6 
union all select 7 
union all select 8 
union all select 9) as e) v 
where this_date <= date(@end_date); 

這會生成一個表,其中包含@start_date和@end_date之間的每個日期。要縮小到每週重複是容易的,我需要做的就是添加(每週星期四的例子):

and dayofweek(this_date) = 5 

的事情是,我無法弄清楚如何做到每兩週或每月從這裏過濾。這是所有這些工作的最後一部分。

非常感謝。

+0

這是一個衆所周知難以解決的難題。閱讀這本書。 http://www.worldcat.org/title/dreaming-in-code-two-dozen-programmers-three-years-4732-bugs-and-one-quest-for-transcendent-software/oclc/70174970 –

回答

0

每月,你將使用day()功能:

where day(this_date) = 5 

月內的第5位。

對於每兩週(每兩個星期),你應該減去一些典型的日期和使用MOD:

where mod(datediff(this_date, '2001-01-01'), 14) = 5 

對於一週中的一天,每隔一週。