我需要帮助(为了更好地理解,请参见附图),因为我完全无助 .
如你所见,我有用户,他们将我们的开始和结束日期时间存储在我的数据库中,如YYYY-mm-dd H:i:s . 现在我需要根据最常见的时间范围重叠(对于大多数用户)找出所有用户的重叠 . 我想为大多数用户提供3个最常访问的数据时间重叠 . 我该怎么做?
我不知道我应该使用哪个mysql查询,或者最好从数据库中选择所有日期时间(开始和结束)并在php中处理它(但是如何?) . 如图所示,结果应该是例如时间8.30-10.00是用户A B C D的结果 .
Table structure:
UserID | Start datetime | End datetime
--------------------------------------
A | 2012-04-03 4:00:00 | 2012-04-03 10:00:00
A | 2012-04-03 16:00:00 | 2012-04-03 20:00:00
B | 2012-04-03 8:30:00 | 2012-04-03 14:00:00
B | 2012-04-06 21:30:00 | 2012-04-06 23:00:00
C | 2012-04-03 12:00:00 | 2012-04-03 13:00:00
D | 2012-04-01 01:00:01 | 2012-04-05 12:00:59
E | 2012-04-03 8:30:00 | 2012-04-03 11:00:00
E | 2012-04-03 21:00:00 | 2012-04-03 23:00:00
4 回答
你实际拥有的是一组集合,并希望确定它们中是否有任何非交叉点 . 这是在尝试查找嵌套集中节点的所有祖先时要求的确切问题 .
我们可以证明,对于每个重叠,至少一个时间窗口将具有落在所有其他重叠时间窗口内的开始时间 . 使用这个小窍门,我们不需要在当天真正构建人工时段 . 只需要一个开始时间,看看它是否与任何其他时间窗口相交,然后只计算交叉点的数量 .
那么查询是什么?
根据您的表大小以及您计划运行此查询的频率,可能值得在其上删除空间索引(请参见下文) .
更新
如果经常运行此查询,则需要使用空间索引 . 由于基于范围的遍历(即start_time落在开始/结束范围之间),BTREE索引不会为您做任何事情 . 它必须是空间的 .
然后,您可以更新上述查询中的ON子句以进行读取
这将为您提供查询的索引遍历 . 如果您经常计划运行查询,请再次执行此操作 .
将空间索引归功于Quassoni's blog .
表似乎很简单 . 我会保持你的SQL查询非常简单:
SELECT * FROM tablename
然后,当您在PHP对象中保存信息时 . 使用循环和比较使用PHP进行处理 .
最简单的形式:
当然,这是非常基本的形式 . 在上面显示的循环中比较它们之前,您可能希望在数组中进行一次循环以首先获取所有userID .
我不会在SQL中做太多,这在编程语言中简单得多,SQL不是用于这样的东西 .
当然,将这一天打入“时间段”是明智的 - 这是统计数据 . 但是一旦你开始处理00:00边界的日期,当你使用连接和内部选择时,事情开始变得蠢 . 特别是对于不太喜欢内部选择的MySQL .
这是一个可能的SQL查询
这是一些伪代码
是的,这会产生
numslots
查询,但没有任何连接,因此它应该非常快 . 您也可以轻松更改分辨率 .另一个积极的事情是,你可以“问问自己”,“我有两个可能的时间段,我需要一个更多人在这里的人,我应该使用哪一个?”并且只使用相应的范围运行两次查询,并且您不会遇到预定义的时间段 .
要仅查找完全重叠(条目仅在覆盖整个插槽时计数),您必须在查询中切换低和高范围 .
您可能已经注意到我不会在可能跨越多天的条目之间添加时间,但是,添加一整天,只会将所有插槽增加一个,这使得它非常无用 . 但是,您可以通过选择
sum(DAY(End) - DAY(Start))
添加它们,并将返回值添加到所有插槽 .这样的事情应该让你开始 -
我们的想法是创建一个派生表,其中包含当天的时间段 . 在这个例子中,我使用了dummy(可以是任何具有所需集合的AI id的表)来通过增量添加30分钟来创建时隙列表 . 然后将其结果与预订相结合,以便能够计算每个时段的书籍数量 .
UPDATE 对于整个日期/时间范围,您可以使用这样的查询来获取所需的其他数据 -
然后可以将这些值替换为原始查询,或者可以将这两个值组合在一起 -
EDIT 我在
GROUP_CONCAT()
中添加了DISTINCT
和ORDER BY
条款以响应您的上一次查询 .请注意,虚拟表中将需要更大范围的ID . 我没有测试过这个查询,所以它可能有语法错误 .