MySQL вопрос по созданию отчета по событиям
Есть таблица events с двумя столбцами: datetime (дата и время события) и type (тип события). В таблицу записываются два типа событий - события включения и события выключения прибора. Требуется посчитать, сколько часов был включен прибор за период времени.
Ответы (2 шт):
Если вкл выкл не последовательно, проверки нет, работать не будет. Временная таблица необязательно, только для наглядности.
-- create
CREATE TABLE events (
ev_datetime datetime PRIMARY KEY,
ev_type int NOT NULL
);
-- insert
INSERT INTO events(ev_type, ev_datetime) values
(1,'2024-02-27 00:54:00'),
(0,'2024-02-27 01:28:00'),
(1,'2024-02-27 02:19:00'),
(0,'2024-02-27 03:13:00'),
(1,'2024-02-27 03:38:00'),
(0,'2024-02-27 03:56:00'),
(1,'2024-02-27 04:48:00'),
(0,'2024-02-27 05:28:00'),
(1,'2024-02-27 06:17:00'),
(0,'2024-02-27 07:06:00'),
(1,'2024-02-27 07:08:00'),
(0,'2024-02-27 07:29:00'),
(1,'2024-02-27 08:01:00'),
(0,'2024-02-27 08:36:00'),
(1,'2024-02-27 09:22:00'),
(0,'2024-02-27 09:25:00'),
(1,'2024-02-27 09:40:00'),
(0,'2024-02-27 10:04:00'),
(1,'2024-02-27 10:15:00'),
(0,'2024-02-27 10:26:00');
SELECT * FROM events;
CREATE TEMPORARY TABLE `tmp_table`
SELECT t1.ev_datetime AS start_time,
MIN(t2.ev_datetime) AS end_time,
TIMESTAMPDIFF(MINUTE,t1.ev_datetime, MIN(t2.ev_datetime) ) AS delta_time
FROM events t1 JOIN events t2 ON t1.ev_datetime < t2.ev_datetime
WHERE t1.ev_type = 1 AND t2.ev_type = 0
group by t1.ev_datetime;
SELECT * FROM tmp_table;
SELECT sum(delta_time)
FROM tmp_table
WHERE start_time>'2024-02-27 03:13:00' and start_time<' 2024-02-27 04:48:00';
Output:
+---------------------+---------+
| ev_datetime | ev_type |
+---------------------+---------+
| 2024-02-27 00:54:00 | 1 |
| 2024-02-27 01:28:00 | 0 |
| 2024-02-27 02:19:00 | 1 |
| 2024-02-27 03:13:00 | 0 |
| 2024-02-27 03:38:00 | 1 |
| 2024-02-27 03:56:00 | 0 |
| 2024-02-27 04:48:00 | 1 |
| 2024-02-27 05:28:00 | 0 |
| 2024-02-27 06:17:00 | 1 |
| 2024-02-27 07:06:00 | 0 |
| 2024-02-27 07:08:00 | 1 |
| 2024-02-27 07:29:00 | 0 |
| 2024-02-27 08:01:00 | 1 |
| 2024-02-27 08:36:00 | 0 |
| 2024-02-27 09:22:00 | 1 |
| 2024-02-27 09:25:00 | 0 |
| 2024-02-27 09:40:00 | 1 |
| 2024-02-27 10:04:00 | 0 |
| 2024-02-27 10:15:00 | 1 |
| 2024-02-27 10:26:00 | 0 |
+---------------------+---------+
+---------------------+---------------------+------------+
| start_time | end_time | delta_time |
+---------------------+---------------------+------------+
| 2024-02-27 00:54:00 | 2024-02-27 01:28:00 | 34 |
| 2024-02-27 02:19:00 | 2024-02-27 03:13:00 | 54 |
| 2024-02-27 03:38:00 | 2024-02-27 03:56:00 | 18 |
| 2024-02-27 04:48:00 | 2024-02-27 05:28:00 | 40 |
| 2024-02-27 06:17:00 | 2024-02-27 07:06:00 | 49 |
| 2024-02-27 07:08:00 | 2024-02-27 07:29:00 | 21 |
| 2024-02-27 08:01:00 | 2024-02-27 08:36:00 | 35 |
| 2024-02-27 09:22:00 | 2024-02-27 09:25:00 | 3 |
| 2024-02-27 09:40:00 | 2024-02-27 10:04:00 | 24 |
| 2024-02-27 10:15:00 | 2024-02-27 10:26:00 | 11 |
+---------------------+---------------------+------------+
+-----------------+
| sum(delta_time) |
+-----------------+
| 18 |
+-----------------+
created 22 hours ago
MySQL online editor
Считаем, что если произошло событие любого типа оно длится до следующего события (строки в таблице).
Поэтому нам нужно знать только тип и время (длительность) до следующего события. События каждого типа сложить отдельно.
При этом две или более подряд идущих строк одного типа нас вовсе не смущают.
Пример
select
sum(case when event_type=1 then elong end) Type1Long
,sum(case when event_type=0 then elong end) Type0Long
from(
select *
,time_to_sec(timediff(lead(event_time,1,event_time)over(order by event_time)
,event_time))elong
from events
)x
where event_time between '2024-26-01 00:00:00' and '2024-03-28 23:59:59'
Или вариант для более ранних версий MySQL
select
sum(case when event_type=1 then elong end) Type1Long
,sum(case when event_type=0 then elong end) Type0Long
from(
select *
,time_to_sec(timediff((select min(event_time) from events e2 where e2.event_time>e.event_time )
,event_time))elong
from events e
)x
where event_time between '2024-26-01 00:00:00' and '2024-03-28 23:59:59'
Выход
| Type1Long | Type0Long |
|---|---|
| 780 | 39240 |
Для данных
| id | event_time | event_type | elong |
|---|---|---|---|
| 1 | 2024-02-28 14:12:00 | 1 | 180 |
| 2 | 2024-02-28 14:15:00 | 0 | 180 |
| 3 | 2024-02-28 14:18:00 | 1 | 240 |
| 4 | 2024-02-28 14:22:00 | 0 | 180 |
| 8 | 2024-02-28 14:25:00 | 0 | 120 |
| 5 | 2024-02-28 14:27:00 | 1 | 120 |
| 6 | 2024-02-28 14:29:00 | 1 | 240 |
| 7 | 2024-02-28 14:33:00 | 0 | 33960 |
| 9 | 2024-02-28 23:59:00 | 0 | 4800 |
| 10 | 2024-02-29 01:19:00 | 0 | 0 |