如何找到状态变化的时差MySQL

时间:2019-01-02 11:46:09

标签: mysql sql database relational-database

我的数据如下。

id  device      state   timestamp
250708  1004-3-007294   9   02/01/2019 9:20
250694  1004-3-007294   8   02/01/2019 9:31
250769  1004-3-007294   7   02/01/2019 10:04
250774  1004-3-007294   5   02/01/2019 10:13
250778  1004-3-007294   4   02/01/2019 10:20
250785  1004-3-007294   11  02/01/2019 10:27
250808  1004-3-007294   4   02/01/2019 10:29
250814  1004-3-007294   11  02/01/2019 10:36
250795  3091-5-007208   7   02/01/2019 10:39
250819  3091-5-007208   5   02/01/2019 10:42
250832  3091-5-007208   4   02/01/2019 10:58
250837  3091-5-007208   11  02/01/2019 11:02
250846  3091-5-007208   4   02/01/2019 11:13

当第一次设备状态从5更改为4时,我需要查找所有设备的时差,因为在我的数据库设备中,设备永远不会再回到状态5,而是将状态从4更改为11、11到4。请帮我写查询。

4 个答案:

答案 0 :(得分:1)

您可以为此使用JOIN。以下假设存在一个正好是5-> 4的过渡,因此不必费心检查它是否是第一个过渡:

SELECT t1.id, t2.id, TIMESTAMPDIFF(SECOND, t1.timestamp,t2.timestamp) AS diff
FROM       t AS t1
INNER JOIN t AS t2 ON t2.device = t1.device AND t2.state = 4 AND t2.timestamp > t1.timestamp
LEFT  JOIN t AS tx ON t1.device = tx.device AND tx.timestamp > t1.timestamp AND tx.timestamp < t2.timestamp
WHERE t1.state = 5 AND tx.id IS NULL

上面的示例中的LEFT连接可确保仅匹配连续的过渡(例如250774与250778和250808连接,但后者将被丢弃)。

Demo on db<>fiddle

答案 1 :(得分:0)

SELECT A.Device, TIMESTAMPDIFF(SECOND,B.t2,A.t1) as differenceintime
FROM
( SELECT device, MIN(timestamp) as t1
  FROM tableName
  WHERE state = 5
  GROUP BY device
) as A
INNER JOIN
( SELECT device, MIN(timestamp) as t2
  FROM tableName
  WHERE state = 4
  GROUP BY device
) as B

ON A.Device = B.Device

答案 2 :(得分:0)

我认为您可以使用条件聚合:

select device,
       timestampdiff(second,
                     min(case when status = 4 then timestamp end),
                     max(case when status = 5 then timestamp end)
                    ) as diff_in_seconds
from t
group by device;

答案 3 :(得分:0)

如果您使用的是更高版本的MySQL,则可以使用LEAD函数获取每一行的下一个状态

SELECT  *,
        LEAD(State) OVER(PARTITION BY device ORDER BY TimeStamp) AS NextState,
        LEAD(TimeStamp) OVER(PARTITION BY device ORDER BY TimeStamp) AS NextTimeStamp
FROM    t;

其中一台设备将提供:

id      device          state   timestamp               NextState       NextTimeStamp
---------------------------------------------------------------------------------------------
250795  3091-5-007208   7       2019-02-01 10:39:00         5           2019-02-01 10:42:00
250819  3091-5-007208   5       2019-02-01 10:42:00         4           2019-02-01 10:58:00   <---
250832  3091-5-007208   4       2019-02-01 10:58:00         11          2019-02-01 11:02:00
250837  3091-5-007208   11      2019-02-01 11:02:00         4           2019-02-01 11:13:00
250846  3091-5-007208   4       2019-02-01 11:13:00        NULL                 NULL

这将使您能够确定状态从5变为4的时间。您只需要将上述查询放入子查询中,并应用where子句:

SELECT  t.device,
        t.TimeStamp AS ChangedToFive,
        t.NextTimeStamp AS ChangedFromFiveToFour
FROM    (   SELECT  *,
                    LEAD(State) OVER(PARTITION BY device ORDER BY TimeStamp) AS NextState,
                    LEAD(TimeStamp) OVER(PARTITION BY device ORDER BY TimeStamp) AS NextTimeStamp
            FROM    t
        ) AS t
WHERE   t.State = 5
AND     t.NextState = 4;

如果您使用的旧版本不支持使用LEAD,那么您将需要使用相关的子查询来复制功能:

SELECT  t.device,
        t.TimeStamp AS ChangedToFive,
        t.NextTimeStamp AS ChangedFromFiveToFour
FROM    (   SELECT  *,
                    (   SELECT  TimeStamp
                        FROM    t AS t2
                        WHERE   t2.Device = t.Device
                        AND     t2.TimeStamp > t.TimeStamp
                        ORDER BY TimeStamp
                        LIMIT 1
                    ) AS NextTimeStamp
            FROM    t
            WHERE   t.State = 5
            AND     (   SELECT  State
                        FROM    t AS t2
                        WHERE   t2.Device = t.Device
                        AND     t2.TimeStamp > t.TimeStamp
                        ORDER BY TimeStamp
                        LIMIT 1
                    ) = 4 -- next state = 4 to satisfy changing from 5 to 4
        ) AS t;

Examples on DB<>Fiddle