SQL Query获取列值的次数和持续时间达到序列中的特定值

时间:2014-06-16 15:37:55

标签: mysql sql

我有一个包含两列 ReceivedOn (日期/时间)和速度(int)的表格 示例数据如下所示

     ReceivedOn       |   Speed
 ----------------------------------------------
 2012-11-05 06:30:00          10
 2012-11-05 06:31:00          45
 2012-11-05 06:32:00          48
 2012-11-05 06:33:00          53
 2012-11-05 06:34:00          47
 2012-11-05 06:35:00          38
 2012-11-05 06:36:00          22
 2012-11-05 06:37:00          36
 2012-11-05 06:38:00          41
 2012-11-05 06:39:00          47
 2012-11-05 06:40:00          49
 2012-11-05 06:41:00          22
 2012-11-05 06:42:00          36

我需要在速度>时对行进行分组40,这样得到的输出就是

       StartTime      |   EndTime               |  Count
 --------------------------------------------------------
 2012-11-05 06:31:00     2012-11-05 06:34:00         4
 2012-11-05 06:38:00     2012-11-05 06:40:00         3

StartTime为速度第一次超过40时的ReceivedOn值,EndTime值为连续记录中最后超过40的ReceivedOn值,Count为连续记录超过40的总数。

我尽我所能但却无法得到它。是否有可能通过SQL查询得到这个? 请建议。提前谢谢。

1 个答案:

答案 0 :(得分:1)

以下是对这些问题的一般回答。 Detect consecutive items meeting particular criteria in a time series

你的具体案例似乎更容易,因为你没有时间差距(希望他说)。您正试图找到时间顺序中的差距。在您的情况下,间隙被定义为> = 40的项目。因此,您正在寻找值小于40的事件序列中的间隙。

这是一个查询,用行号给你的时间序列。

SELECT @RowA := @RowA + 1 AS ROWNUM,
       ReceivedOn, Speed
   FROM (
        SELECT ReceivedOn, Speed
          FROM obs
         WHERE NOT Speed >= 40
   ) AS A
   JOIN (SELECT @RowA := 0) AS B

现在,您使用一些严肃的SQL猴子业务将此序列自行连接到自身。这是这样的:

SELECT B.ReceivedON + INTERVAL 1 MINUTE As StartTime,
       A.ReceivedOn - INTERVAL 1 MINUTE AS EndTime,
       -1 + TIMESTAMPDIFF(MINUTE, B.ReceivedOn, A.ReceivedOn) AS Count
  FROM (
         SELECT @RowA := @RowA + 1 AS ROWNUM,
                ReceivedOn, Speed
           FROM (
              SELECT ReceivedOn, Speed
                FROM obs
               WHERE NOT Speed >= 40
                ) AS A
           JOIN (SELECT @RowA := 0) AS B
       ) AS A
  JOIN (
          SELECT @RowB := @RowB + 1 AS ROWNUM,
                 ReceivedOn, Speed
         FROM (
              SELECT ReceivedOn, Speed
                FROM obs
               WHERE NOT Speed >= 40
              ) AS A
         JOIN (SELECT @RowB := 0) AS B
        ) AS B ON B.ROWNUM+1 = A.ROWNUM
 WHERE TIMESTAMPDIFF(MINUTE, B.ReceivedOn, A.ReceivedOn) > 1

http://sqlfiddle.com/#!2/2cb57/24/0

这看起来非常多毛,但它只是第一个查询与自身ON B.ROWNUM+1 = A.ROWNUM的连接。这使得查询的结果集自身偏移了一行,因此您可以比较连续的行。

这给出了你需要的结果。请注意,如果您的第一次观察是> = 40,则此查询将省略第一个观察序列。