我有一个带有日期时间行的 MySQL 表。如何在 10 分钟内找到所有至少有 5 个条目的群组?
我唯一的想法是编写一个程序(用任何语言)并循环时间戳,始终检查 5 (..) 个连续条目,计算最后一个和第一个之间的时间跨度并检查它是否低于限制.
这也可以使用单个 SQL 查询来完成吗?
(场景经过简化,数字只是示例。)
根据要求,这里有一个示例:
id | timestamp | other_column
---|---------------------|-------------
3 | 2017-01-01 11:00:00 | thank
2 | 2017-01-01 11:01:00 | you
1 | 2017-01-01 11:02:00 | for
* 6 | 2017-01-01 11:20:00 | your
* 5 | 2017-01-01 11:21:00 | efforts
* 4 | 2017-01-01 11:22:00 | to
* 7 | 2017-01-01 11:23:00 | help
* 8 | 2017-01-01 11:24:00 | me
9 | 2017-01-01 11:40:00 | :
10 | 2017-01-01 11:41:00 | )
如果计数限制为 5,时间跨度限制为 10 分钟,我希望获取标有“*”的条目。 “id”列是表的主键,但顺序并不总是时间戳的顺序。 “other_column”用于 where 子句。该表大约有 100 万个条目。
最佳答案
尝试从逻辑上分解它。对于伪代码位,我很抱歉,我的时间有点短。
select t1.id, t1.timestamp, t2.timestamp
from yourtable t1
inner join yourtable t2 on t2.timestamp >= t1.timestamp and t2.timestamp < (t1.timestamp + 20 minutes)
(加20分钟不会起作用,请使用适当的添加功能)
因此,这将为您提供一个相对庞大的列表,其中包含 20 分钟时间间隔内与任何其他 ID 连接的所有 ID(包括一行)。 (补充一下,此时我只挑选出该组的第一行,更容易通过此时间戳加上 20 分钟来获取此处的“标题行”,并在下一步中担心其余部分)如果我们按ID 和时间,我们得到 20 分钟内有多少行的计数:
select id, t1.timestamp, count(1)
from yourtable t1
inner join yourtable t2 on t2.timestamp >= t1.timestamp and t2.timestamp < (t1.timestamp + 20 minutes)
group by id, t1.timestamp
having count(1) > 4
现在将为您提供所有 ID 及其时间戳的列表,该时间戳在距该时间戳 20 分钟内有其自身和 4 个其他记录或更多记录。现在这取决于您想要如何从这里进行分组,如果您想要 5 行中的每一行,我们可以调用子查询上面的查询并将其连接回主表以获取您想要返回的行。
select t3.*
from
(select id, t1.timestamp, count(1)
from yourtable t1
inner join yourtable t2
on t2.timestamp >= t1.timestamp and t2.timestamp < (t1.timestamp + 20 minutes)
group by id, t1.timestamp
having count(1) > 4) a
inner join yourtable t3 on t3.timestamp >= a.timestamp and t3.timestamp < (a.timestamp + 20 minutes)
这应该会给你 ID 4-8 和返回的信息(按照你认为合适的顺序)。
抱歉,我没有时间测试,但逻辑应该可行。
关于MySQL:选择一定时期内具有一定数量的条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47167774/