计算一段时间内,一组较小的时间段

时间:2013-09-09 17:03:01

标签: mysql

使用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()

1 个答案:

答案 0 :(得分:0)

是的,可能使用GROUP BYHAVING,使用一些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 的行是您的行数。不要在大桌子上运行它。

相关问题