使用MySQL,我希望能够找出在特定代码的任何5分钟内,在过去30分钟内是否有4个条目。
name stamp code
a 2013-02-03 13:12:01 red
b 2013-02-03 13:23:01 red
c 2013-02-03 13:23:11 red
d 2013-02-03 13:24:01 green
e 2013-02-03 13:24:05 red
f 2013-02-03 13:24:21 red
g 2013-02-03 13:25:01 red
h 2013-02-03 13:48:01 red
所以,在2013-02-03 13:50:00,我运行一个查询,它返回最近30分钟内的条目数,在5分钟内有一组4个或更多条目时间块和第一个匹配条目的标记,但仅用于代码红色条目。
我想使用此示例表的结果将是:5,2013-02-03 13:23:01
单个查询可能吗?谢谢!
编辑:查看此查询的任何问题?
SELECT COUNT(*), rolling.stamp
FROM mytable thisrow JOIN mytable rolling
ON (thisrow.stamp BETWEEN rolling.stamp AND
rolling.stamp + INTERVAL 5 MINUTE)
WHERE rolling.stamp >= DATE_SUB(NOW(), INTERVAL 30 MINUTE)
AND code = 'red'
GROUP BY 2 HAVING COUNT(*) >= 4
当针对上表运行时,我得到了所需的“5,2013-02-03 13:23:01”。
P.S。我将'2013-02-03 13:50:00'替换为此示例的now()
答案 0 :(得分:0)
是的,可能使用GROUP BY
和HAVING
,使用一些UNIX_TIMESTAMP
舍入(从stamp % 300
减去stamp
)分组为300秒的块(5分钟)。
SELECT COUNT(*), MIN(stamp)
FROM mytable
WHERE stamp >= NOW() - INTERVAL 30 minute
GROUP BY
FROM_UNIXTIME(
UNIX_TIMESTAMP(stamp) -
MOD(UNIX_TIMESTAMP(stamp),300)
)
HAVING COUNT(*) >= 4
这假设您的意思是时钟块而不是滚动块,即您想要从00:00:00到00:04:59等,而不是从13:23:01到13:28:00。这会导致“30分钟前”规则出现一些问题,因此您可能需要仔细考虑这一问题。
编辑:很好看,因为你坚持让它成为一个滚动块...让我们添加一些美味的表现非常好的加入。SELECT COUNT(*), rolling.stamp
FROM mytable thisrow JOIN mytable rolling
ON (thisrow.stamp BETWEEN rolling.stamp AND
rolling.stamp + INTERVAL 5 MINUTE)
WHERE rolling.stamp >= NOW() - INTERVAL 30 minute
GROUP BY 2 HAVING COUNT(*) >= 4;
如果你在stamp
上有一个索引,它会表现得更好,但这实际上是一个交叉连接,具有可怕的,可怕的性能,你在 n ²上过滤 n 的行是您的行数。不要在大桌子上运行它。