Mysql 选择持续超过1秒的状态
我有一个问题看起来很简单,但我找不到解决办法 所以,我有一张桌子,上面有两个可乐,像这样: 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 OnMysql 选择持续超过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
你们能给我一些线索吗?非常感谢 简单的
分组依据
和总和
无法在当前数据集上执行此操作,因此我的想法是添加一个帮助器列:
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;