PHP/MySQL:对数据库中的重复事件进行建模,但查询日期范围
Posted
技术标签:
【中文标题】PHP/MySQL:对数据库中的重复事件进行建模,但查询日期范围【英文标题】:PHP/MySQL: Model repeating events in a database but query for date ranges 【发布时间】:2012-11-27 22:29:12 【问题描述】:我正在开发一个(我打算成为的)简单的 php/mysql 应用程序。作为其中的一部分,我希望能够对重复事件进行建模,但是我需要能够查询两个日期之间发生的所有事件(包括重复事件)。这些事件只有一个日期,一天中的时间无关紧要。
我一直在研究这个问题,并研究了各种方法,包括 Calendar Recurring/Repeating Events - Best Storage Method 和 Repeating calendar events and some final maths。
但是,我在网上找到的任何支持这一点的数据库模式示例似乎只支持查询某一天发生的事件。不支持在某个日期范围内发生的事件。
作为一个抽象的例子
事件表(带有某种重复表示):
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
是否有支持此类查询的数据库架构?对于两天之间发生的任何事件(包括重复事件),我将如何在该架构上进行查询?
或者也许是用于重复事件的设计模式?
【问题讨论】:
这非常困难,并且可能以非常复杂的模式和/或查询告终。在 PHP 中通过对事件表的简单查询来构造结果集不是更容易(也更有效)吗? 也许,但我担心随着时间的推移,您可能会遇到一个结果集充满陈旧重复(或在您的日期范围内未出现的重复)并且必须修剪这些的潜在问题退出应用程序。 【参考方案1】:我不太了解您的目标...也许您正在寻找 SQL 中的 UNIQUE 函数?
【讨论】:
可能不仅我误解了一些问题,而且我也无法预测我能获得的选票。猜猜,除非你知道确切的答案,否则最好不要写任何东西,否则要求更多信息或建议一些东西会让你被否决:))) 没错,您可以删除此答案以防止更多的反对意见【参考方案2】:我将创建一个只有一个名为 id
的列的计数表,并用从 0 到 500 的数字填充该表。现在我们可以轻松地使用它来进行选择,而不是使用 while 循环。
Id
-------------------------------------
0
1
2
etc...
然后我会将事件存储在一个带有Name as varchar
、startdate 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 的计数表。您可以缓存并且不必再次计算的所有内容都是好的。
【讨论】:
以上是关于PHP/MySQL:对数据库中的重复事件进行建模,但查询日期范围的主要内容,如果未能解决你的问题,请参考以下文章
重复事件(表现形态:活跃留存复购)建模(生存分析)的案例学习笔记