Mysql 选择持续超过1秒的状态

Mysql 选择持续超过1秒的状态,mysql,sql,Mysql,Sql,我有一个问题看起来很简单,但我找不到解决办法 所以,我有一张桌子,上面有两个可乐,像这样: Time Status 00:00:00.111 Off 00:00:00.222 On 00:00:00.345 On 00:00:01.555 On 00:00:01.666 Off 00:00:02.222 On 00:00:02.422 On 00:00:02.622

我有一个问题看起来很简单,但我找不到解决办法

所以,我有一张桌子,上面有两个可乐,像这样:

Time Status 00:00:00.111 Off 00:00:00.222 On 00:00:00.345 On 00:00:01.555 On 00:00:01.666 Off 00:00:02.222 On 00:00:02.422 On 00:00:02.622 Off 00:00:05.888 Off 00:00:05.999 Off 时间状态 00:00:00.111关闭 00:00:00.222开 00:00:00.345开 00:00:01.555 On 00:00:01.666关闭 00:00:02.222开 00:00:02.422 On 00:00:02.622关 00:00:05.888关闭 00:00:05.999关闭 我想选择所有持续超过1秒的状态, 在本例中,我需要以下序列:

00:00:00.222 On 00:00:00.345 On 00:00:01.555 On 00:00:00.222开 00:00:00.345开 00:00:01.555 On
你们能给我一些线索吗?非常感谢

简单的
分组依据
总和
无法在当前数据集上执行此操作,因此我的想法是添加一个帮助器列:

CREATE TABLE someTable(
`time` DATETIME,
status CHAR(3),
helperCol INT
);
helperCol是一个INT,将按如下方式设置:

CREATE PROCEDURE setHelperCol() 
BEGIN
  DECLARE finished,v_helperCol INT;
  DECLARE status CHAR(3);
  DECLARE ts DATETIME;
  DECLARE CURSOR st FOR SELECT `time`,status,helperCol FROM someTable WHERE helperCol IS NOT NULL; -- Handy for re-use: No need to go over all data, so you can save the helperCol as permanent value.
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
  SELECT @maxVal:=MAX(helperCol) FROM helperCol;

  SET finished=0;
  SET helperCol=@maxVal;
  IF(!helperCol>0) SET helperCol=1;
  OPEN st;
  FETCH ts,status,v_helperCol FROM st;
  WHILE(finished=0) DO
    IF(status='Off') v_helperCol=v_helperCol+1;
    UPDATE someTable SET helperCol=v_helperCol WHERE `time`=ts; -- Assuming `time` is unique;
    FETCH ts,status,v_helperCol FROM st;
  END WHILE;
  CLOSE st;
END;
执行该过程,结果是:

Time               Status  helperCol
00:00:00.111       Off      2
00:00:00.222       On       2
00:00:00.345       On       2
00:00:01.555       On       2
00:00:01.666       Off      3
00:00:02.222       On       3
00:00:02.422       On       3
00:00:02.622       Off      4
现在可以对其进行分组和处理:

SELECT MAX(`time`)-MIN(`time`) AS diffTime
FROM someTable
WHERE status='ON'
GROUP BY helperCol
HAVING MAX(`time`)-MIN(`time`)>1;
其结果是(您需要搜索要应用于
MAX-MIN
部分的正确
datetime
函数):

备选方案:


您也可以在存储过程中处理
MAX-MIN
,但这不会像helperColumn解决方案那样有效地重复。

数据类型是什么?它是哪个版本的SQL/MySQL?我想这会有帮助:在你想要的前两个结果之间,不到一秒钟。为什么?谢谢你,Marekful。我的意思是On的状态从00:00.222持续到00:00:01.555,持续时间大于1秒。那么您的描述不准确。您希望选择第一行和最后一行之间经过的时间超过1秒并后跟“关闭”的所有连续“打开”状态行。这是正确的吗?是的,这正是我想要的,我会修改帖子,谢谢。嗨,诺伯特,非常感谢你的回答,解决方案看起来很好。然而,在我的情况下,我会有一个巨大的表,我需要选择所有这些状态持续超过一秒钟。我会进一步考虑这个问题,我通过使过程递增来考虑大表:当添加数据时,过程只需处理新零件。通过在
helperCol
上添加索引,速度会更快。
SELECT a.time start
     , MIN(c.time) end
     , TIMEDIFF(MIN(c.time),a.time) duration
  FROM 
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) a
  LEFT
  JOIN
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) b
    ON b.status = a.status
   AND b.rank = a.rank - 1
  JOIN
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) c
    ON c.rank >= a.rank
  LEFT 
  JOIN 
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) d
    ON d.status = c.status 
   AND d.rank = c.rank + 1
 WHERE b.rank IS NULL
   AND d.rank IS NULL
   AND a.status = 1
 GROUP
    BY a.time
HAVING duration >= 1;
SELECT a.time start
     , MIN(c.time) end
     , TIMEDIFF(MIN(c.time),a.time) duration
  FROM 
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) a
  LEFT
  JOIN
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) b
    ON b.status = a.status
   AND b.rank = a.rank - 1
  JOIN
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) c
    ON c.rank >= a.rank
  LEFT 
  JOIN 
     ( SELECT x.*,  COUNT(*) rank FROM my_table x JOIN my_table y ON y.time <= x.time GROUP BY time ) d
    ON d.status = c.status 
   AND d.rank = c.rank + 1
 WHERE b.rank IS NULL
   AND d.rank IS NULL
   AND a.status = 1
 GROUP
    BY a.time
HAVING duration >= 1;
SELECT time
     , status 
     , cumulative
  FROM 
     ( SELECT *
            , CASE WHEN @prev = status THEN @i:=@i+duration ELSE @i:=0 END cumulative
            , @prev:=status
         FROM 
            ( SELECT x.*
                   , TIME_TO_SEC(MIN(y.time))-TIME_TO_SEC(x.time) duration 
                FROM my_table x 
                JOIN my_table y 
                  ON y.time > x.time 
               GROUP 
                  BY x.time
            ) n
        ORDER 
           BY time
     ) a
 WHERE cumulative >= 1
   AND status = 1;