Есть ли эффективный способ получить суммы за несколько временных диапазонов для нескольких групп (пример ниже)?
Я использую MySQL 8.
PS: Я очень старался сформулировать этот вопрос настолько ясно, насколько это возможно. Я с радостью приму предложения, чтобы сделать его более ясным / понятным ...
OBS:
RAW ТАБЛИЦА:
SELECT* FROM pluv_reg ORDER BY dth DESC;
id dth valor
1 2020-05-07 16:20:00 5.0
2 2020-05-07 16:20:00 5.0
3 2020-05-07 16:20:00 5.0
4 2020-05-07 16:20:00 5.0
1 2020-05-07 16:15:00 5.0
2 2020-05-07 16:15:00 5.0
...
ЖЕЛАТЕЛЬНЫЙ ВОЗВРАТ:
id dth m05 m15 m30 h01 h24 h48 h96
1 2020-05-07 16:20:00 5.0 15.0 60.0 60.0 100.0 100.0 196.0
2 2020-05-07 16:20:00 5.0 15.0 60.0 60.0 100.0 100.0 197.0
3 2020-05-07 16:20:00 5.0 15.0 60.0 60.0 100.0 100.0 198.0
4 2020-05-07 16:20:00 5.0 15.0 60.0 60.0 100.0 100.0 199.0
1 2020-05-07 16:15:00 5.0 15.0 55.0 55.0 95.0 95.0 191.0
2 2020-05-07 16:15:00 5.0 15.0 55.0 55.0 95.0 95.0 192.0
3 2020-05-07 16:15:00 5.0 15.0 55.0 55.0 95.0 95.0 193.0
...
LEGEND
Column m05 -> Sum of "valor" of the last 05 minutes for that "id" at that time
...
Column m30 -> Sum of "valor" of the last 30 minutes for that "id" at that time
...
Column h48 -> Sum of "valor" of the last 48 hours for that "id" at that time
ТЕКУЩИЙ ЗАПРОС:
SELECT *
FROM (
SELECT pluv_reg.id,
pluv_reg.dth,
SUM(pluv_reg.valor) OVER w05 AS 'm05',
SUM(pluv_reg.valor) OVER w15 AS 'm15',
SUM(pluv_reg.valor) OVER w30 AS 'm30',
SUM(pluv_reg.valor) OVER w1 AS 'h01',
SUM(pluv_reg.valor) OVER w24 AS 'h24',
SUM(pluv_reg.valor) OVER w48 AS 'h48',
SUM(pluv_reg.valor) OVER w96 AS 'h96'
FROM pluv_reg
# this WHERE clause ensures that all the rows I need have the correct values ______________________________
WHERE pluv_reg.dth > DATE_SUB(CAST('2020-05-07 16:20:00' AS DATETIME), INTERVAL 98 HOUR)
WINDOW w05 AS (PARTITION BY id ORDER BY dth RANGE INTERVAL '0:04' HOUR_MINUTE PRECEDING),
w15 AS (PARTITION BY id ORDER BY dth RANGE INTERVAL '0:14' HOUR_MINUTE PRECEDING),
w30 AS (PARTITION BY id ORDER BY dth RANGE INTERVAL '0:29' HOUR_MINUTE PRECEDING),
w1 AS (PARTITION BY id ORDER BY dth RANGE INTERVAL '0:59' HOUR_MINUTE PRECEDING),
w24 AS (PARTITION BY id ORDER BY dth RANGE INTERVAL '23:59' HOUR_MINUTE PRECEDING),
w48 AS (PARTITION BY id ORDER BY dth RANGE INTERVAL '47:59' HOUR_MINUTE PRECEDING),
w96 AS (PARTITION BY id ORDER BY dth RANGE INTERVAL '95:59' HOUR_MINUTE PRECEDING)
) subquery
# this HAVING clause returns only the rows I need _____________________________________________________________
HAVING subquery.dth >= DATE_SUB(CAST('2020-05-07 16:20:00' AS DATETIME), INTERVAL 2 HOUR);
Мой ТЕКУЩИЙ ЗАПРОС (см. Выше) работает, но на моей реальной производственной таблице он занимает очень много времени (до 10 секунд. Я хотел бы ускорить работу до чего-то вроде В 10 раз быстрее, по крайней мере).
Проблема с моим ТЕКУЩИЙ ЗАПРОС заключается в том, что он вычисляет эти суммы для всех строк за последние 98 часов ( WHERE pluv_reg.dth> DATE_SUB (CAST ('2020-05-07 16:20:00' AS DATETIME), ИНТЕРВАЛ 98 ЧАСОВ) ), хотя мне нужны только эти суммы за последние 2 часа ( HAVING subquery.dth> = DATE_SUB (CA ST ('2020-05-07 16:20:00' КАК ДАТА ВРЕМЯ), ИНТЕРВАЛ 2 ЧАСА) );
В приведенном ниже примере подзапрос создает 32 строки (40.000 на производстве). Предложение HAVING фильтрует его только до 20 строк (700 на производстве) - это единственные строки, которые мне нужны.
Операторы CREATE и INSERT:
CREATE TABLE pluv_reg (
id INT,
dth DATETIME,
valor DECIMAL(5,1),
PRIMARY KEY(id, dth)
);
INSERT INTO pluv_reg (id,dth,valor) VALUES
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 0 MINUTE), 5),
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 5 MINUTE), 5),
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 MINUTE), 5),
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 15 MINUTE), 5),
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 20 MINUTE), 40),
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 HOUR), 40),
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 60 HOUR), 72),
(1, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 90 HOUR), 24),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 0 MINUTE), 5),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 5 MINUTE), 5),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 MINUTE), 5),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 15 MINUTE), 5),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 20 MINUTE), 40),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 HOUR), 40),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 60 HOUR), 72),
(2, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 90 HOUR), 24),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 0 MINUTE), 5),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 5 MINUTE), 5),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 MINUTE), 5),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 15 MINUTE), 5),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 20 MINUTE), 40),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 HOUR), 40),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 60 HOUR), 72),
(3, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 90 HOUR), 24),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 0 MINUTE), 5),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 5 MINUTE), 5),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 MINUTE), 5),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 15 MINUTE), 5),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 20 MINUTE), 40),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 10 HOUR), 40),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 60 HOUR), 72),
(4, (CAST('2020-05-07 16:20:00' AS DATETIME) - INTERVAL 90 HOUR), 24)
;