1

使用 MySQL,我希望能够找出某个代码在过去 30 分钟内的任何 5 分钟内是否有 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”。

PS我用'2013-02-03 13:50:00'代替了这个例子的now()

4

1 回答 1

0

是的,可以使用 aGROUP BY和 a HAVING,使用一些舍入(从UNIX_TIMESTAMP减去)分组为 300 秒(5 分钟)的块。stamp % 300stamp

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是你的行数。不要在大桌子上运行它。

于 2013-09-09T17:11:24.837 回答