Если вы используете более позднюю версию 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;
Примеры на БД <> Fiddle