简体   繁体   English

PHP / MySQL:模拟数据库中的重复事件,但查询日期范围

[英]PHP/MySQL: Model repeating events in a database but query for date ranges

I'm working on a (what I was intending to be) simple PHP/MySQL app. 我正在研究(我打算成为的)简单的PHP / MySQL应用程序。 As part of it I'd like to be able to model repeating events, however I need to be able to query all the events that happened between two dates (including repeated events). 作为其中的一部分,我希望能够为重复事件建模,但是我需要能够查询两个日期之间发生的所有事件(包括重复事件)。 The events only have a date, the time of day doesn't matter. 事件只有一个日期,一天中的时间无关紧要。

I've been researching this and have looked in to various approaches including Calendar Recurring/Repeating Events - Best Storage Method and Repeating calendar events and some final maths . 我一直在研究这个并且已经研究了各种方法,包括日历重复/重复事件 - 最佳存储方法重复日历事件以及一些最终数学

However, any example of a database schema supporting this that I find online, only seems to support querying for events that happened on a certain day. 但是,我在网上找到的支持这种情况的数据库模式的任何示例似乎都支持查询某一天发生的事件。 There is no support for events that happened between a range of dates. 不支持在一系列日期之间发生的事件。

As an abstract example 作为一个抽象的例子

Events table (with some sort of repeat representation): 事件表(带有某种重复表示):

Event   | Start Date   |   Repeats
-------------------------------------
Meeting | 10/Dec/2012  |   Every 7 days
Lunch   | 10/Dec/2012  |   Every 1 days

Target result of abstract query SELECT Events BETWEEN 09/Dec/2012 AND 20/Dec/2012 抽象查询的目标结果SELECT Events BETWEEN 09/Dec/2012 AND 20/Dec/2012

Event   |  Date        |   Repeats
-------------------------------------
Meeting | 10/Dec/2012  |   Every 7 days
Meeting | 17/Dec/2012  |   Every 7 days
Lunch   | 10/Dec/2012  |   Every 1 days
Lunch   | 11/Dec/2012  |   Every 1 days
Lunch   | 12/Dec/2012  |   Every 1 days
Lunch   | 13/Dec/2012  |   Every 1 days
etc...
Lunch   | 20/Dec/2012  |   Every 1 days

Is there a database schema that will support these kind of queries? 是否有支持这类查询的数据库架构? How would I go around making a query on that schema for any event (including repeating events) that happened between two days? 如何在两天之间发生的任何事件(包括重复事件)对该模式进行查询?

Or perhaps a design pattern that is used for repeating events? 或者也许是用于重复事件的设计模式?

I would create a tally table with just one col called id and fill that table with numbers from 0 to 500. Now we easily use that to make selections instead of using a while loop. 我将使用一个名为id col创建一个计数表,并用0到500的数字填充该表。现在我们可以轻松地使用它来进行选择而不是使用while循环。

Id
-------------------------------------
0
1
2
etc...

Then i'd store the events in a table with Name as varchar , startdate as datetime and repeats as int 然后我将事件存储在一个表中,其中Name as varcharstartdate as datetimerepeats as int

Name    | StartDate            |   Repeats
-------------------------------------
Meeting | 2012-12-10 00:00:00  |   7
Lunch   | 2012-12-10 00:00:00  |   1

Now we can use the tally table to select all dates between two dates by using: 现在我们可以使用计数表来选择两个日期之间的所有日期:

SELECT DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY) as showdate
FROM `tally`
WHERE (DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY)<='2012-12-20 00:00:00')
ORDER BY Id ASC
ShowDate
-------------------------------------
2012-12-09 00:00:00
2012-12-10 00:00:00
2012-12-11 00:00:00
2012-12-12 00:00:00
2012-12-13 00:00:00
2012-12-14 00:00:00
2012-12-15 00:00:00
2012-12-16 00:00:00
2012-12-17 00:00:00
2012-12-18 00:00:00
2012-12-19 00:00:00
2012-12-20 00:00:00

Then we join this on the events table to calculate the difference between the startdate and the showdate. 然后我们在事件表上加入它来计算startdate和showdate之间的差异。 We devided the results of this by the repeats column and if the remainder is 0 , we have match. 我们通过repeats列将结果分开,如果余数为0 ,我们匹配。

All combined becomes: 所有组合成为:

SELECT E.Id, E.Name, E.StartDate, E.Repeats, A.ShowDate, DATEDIFF(E.StartDate, A.ShowDate) AS diff
FROM events AS E, (
    SELECT DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY) as showdate
    FROM `tally`
    WHERE (DATE_ADD('2012-12-09 00:00:00',INTERVAL Id DAY)<='2012-12-20 00:00:00')
    ORDER BY Id ASC
) a
WHERE MOD(DATEDIFF(E.StartDate, A.ShowDate), E.Repeats)=0
AND A.ShowDate>=E.StartDate

Which results in 结果如何

Id  | Name       |StartDate             | Repeats   | ShowDate              | diff
---------------------------------------------------------------------------------
1   | Meeting    | 2012-12-10 00:00:00  | 7         | 2012-12-10 00:00:00   | 0
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-10 00:00:00   | 0
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-11 00:00:00   | -1
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-12 00:00:00   | -2
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-13 00:00:00   | -3
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-14 00:00:00   | -4
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-15 00:00:00   | -5
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-16 00:00:00   | -6
1   | Meeting    | 2012-12-10 00:00:00  | 7         | 2012-12-17 00:00:00   | -7
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-17 00:00:00   | -7
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-18 00:00:00   | -8
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-19 00:00:00   | -9
2   | Lunch      | 2012-12-10 00:00:00  | 1         | 2012-12-20 00:00:00   | -10

Now you could (and should!) speed things up. 现在你可以(并且应该!)加快速度。 For instance by directly storing dates in a table so you can just select all dates directly instead of using a tally table with dateadd. 例如,通过直接在表中存储日期,您可以直接选择所有日期,而不是使用带有dateadd的计数表。 Every thing you can cache and dont have to calculate again is good. 你可以缓存并且不必再次计算的每件事都很好。

我不太明白你的目标......也许你在SQL中寻找UNIQUE函数?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM