Вот подход с использованием пользовательских переменных. Следует отметить, что даже функции Windowing не могут быть использованы в этой задаче простым способом. Тем не менее, ваша версия старая, и их тоже не поддерживают. Следующее решение является общим и обрабатывает сценарий, если вы не используете условие WHERE
для device_id
и хотите несколько device_id
в наборе результатов.
Общая идея здесь заключается в том, что мы вычисляем «островной номер» (обозначаемый в запросе как chng
) для последовательных строк (на основе отметки времени), имеющих одинаковые значения device_id
и status
(либо ON, либоOFF). В конце концов, мы можем отфильтровать только те острова, которые имеют статус ON
, а затем выполнить агрегацию, чтобы получить MIN()
(метка времени начала) и MAX()
(метка времени остановки).
Схема(MySQL v5.7)
CREATE TABLE device_stats
(`id` int, `device_id` varchar(11), `status` varchar(3), `timestamp` int, `device_iddr` int)
;
INSERT INTO device_stats
(`id`, `device_id`, `status`, `timestamp`, `device_iddr`)
VALUES
(16416, 'LivingLight', 'OFF', 1570080242, 1),
(16427, 'LivingLight', 'OFF', 1570080363, 1),
(16438, 'LivingLight', 'OFF', 1570080483, 1),
(16449, 'LivingLight', 'OFF', 1570080602, 1),
(16460, 'LivingLight', 'OFF', 1570080723, 1),
(16471, 'LivingLight', 'OFF', 1570080842, 1),
(16482, 'LivingLight', 'ON', 1570080963, 1),
(16493, 'LivingLight', 'ON', 1570081083, 1),
(16504, 'LivingLight', 'ON', 1570081203, 1),
(16515, 'LivingLight', 'ON', 1570081323, 1),
(16526, 'LivingLight', 'ON', 1570081443, 1),
(16537, 'LivingLight', 'ON', 1570081563, 1),
(16548, 'LivingLight', 'ON', 1570081682, 1),
(16559, 'LivingLight', 'ON', 1570081803, 1),
(16570, 'LivingLight', 'ON', 1570081922, 1),
(16581, 'LivingLight', 'ON', 1570082042, 1),
(16592, 'LivingLight', 'ON', 1570082163, 1),
(16603, 'LivingLight', 'ON', 1570082283, 1),
(16614, 'LivingLight', 'ON', 1570082402, 1),
(16625, 'LivingLight', 'ON', 1570082523, 1),
(16636, 'LivingLight', 'ON', 1570082643, 1),
(16647, 'LivingLight', 'ON', 1570082762, 1),
(16658, 'LivingLight', 'ON', 1570082882, 1),
(16669, 'LivingLight', 'OFF', 1570083003, 1),
(16680, 'LivingLight', 'OFF', 1570083123, 1),
(16691, 'LivingLight', 'OFF', 1570083242, 1),
(16702, 'LivingLight', 'OFF', 1570083363, 1),
(16713, 'LivingLight', 'OFF', 1570083483, 1),
(16724, 'LivingLight', 'OFF', 1570083603, 1),
(16735, 'LivingLight', 'OFF', 1570083722, 1),
(16746, 'LivingLight', 'OFF', 1570083843, 1),
(16757, 'LivingLight', 'OFF', 1570083963, 1),
(16768, 'LivingLight', 'OFF', 1570084083, 1),
(16779, 'LivingLight', 'OFF', 1570084202, 1),
(16790, 'LivingLight', 'OFF', 1570084323, 1),
(16801, 'LivingLight', 'OFF', 1570084442, 1),
(16812, 'LivingLight', 'ON', 1570084563, 1),
(16823, 'LivingLight', 'ON', 1570084683, 1),
(16834, 'LivingLight', 'OFF', 1570084803, 1),
(16845, 'LivingLight', 'OFF', 1570084922, 1)
;
Запрос № 1
SELECT
device_id, MIN(timestamp) AS start, MAX(timestamp) AS stop
FROM
(
SELECT
@c := IF(@s <> status OR @d <> device_id , @c+1, @c) AS chng,
@s := status AS status,
@d := device_id AS device_id,
timestamp
FROM
(
SELECT device_id, status, timestamp
FROM device_stats
WHERE device_id = 'LivingLight'
AND timestamp BETWEEN 1570080242 AND 1570084922
ORDER BY device_id, timestamp
) t1
CROSS JOIN (SELECT @s := '',
@d := '',
@c := 0) vars
) t2
WHERE t2.status = 'ON'
GROUP BY device_id, chng;
| device_id | start | stop |
| ----------- | ---------- | ---------- |
| LivingLight | 1570080963 | 1570082882 |
| LivingLight | 1570084563 | 1570084683 |
Просмотр на БД Fiddle