5

我正在开发一个(我打算成为的)简单的 PHP/MySQL 应用程序。作为其中的一部分,我希望能够对重复事件进行建模,但是我需要能够查询两个日期之间发生的所有事件(包括重复事件)。这些事件只有一个日期,一天中的时间无关紧要。

我一直在研究这一点,并研究了各种方法,包括 Calendar Recurring/Repeating Events - Best Storage Method and Repeating calendar events 和一些最终数学

但是,我在网上找到的任何支持这一点的数据库模式示例似乎只支持查询某一天发生的事件。不支持在一系列日期之间发生的事件。

作为一个抽象的例子

事件表(具有某种重复表示):

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

抽象查询的目标结果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

是否有支持此类查询的数据库模式?对于两天之间发生的任何事件(包括重复事件),我将如何围绕该模式进行查询?

或者可能是用于重复事件的设计模式?

4

2 回答 2

5

我将创建一个只调用一个 col 的计数表,id并用从 0 到 500 的数字填充该表。现在我们可以轻松地使用它来进行选择,而不是使用 while 循环。

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

然后我将事件存储在一个表中Name as varcharstartdate as datetime并且repeats as int

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

现在我们可以使用计数表来选择两个日期之间的所有日期:

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

然后我们在事件表上加入它来计算开始日期和显示日期之间的差异。我们将结果除以repeats列,如果余数为0,则匹配。

所有组合变成:

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

这导致

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

现在你可以(而且应该!)加快速度。例如,通过直接将日期存储在表中,您可以直接选择所有日期,而不是使用带有 dateadd 的计数表。您可以缓存并且不必再次计算的每一件事都是好的。

于 2012-12-10T14:21:36.667 回答
-3

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

于 2012-12-10T14:08:06.247 回答