Допустим, у вас есть гигантская таблица measure
с двумя столбцами datestamp
и temp
.
Допустим, вы хотите видеть температуру каждые шесть минут (10 раз в час) в течение последней недели. Вы можете делать такие вещи. Мы скоро дойдем до определения trunc
.
SELECT trunc(datestamp) datestamp, AVG(temp) temp
FROM measure
WHERE datestamp >= CURDATE() - INVERVAL 7 DAY
GROUP BY trunc(datestamp)
ORDER BY trunc(datestamp)
Это работает для любого разумного определения trunc
. В этом случае trunc(t)
возвращает начало шестиминутного периода, в котором происходит t
. Итак, trunc('1942-12-07 08:45:17')
дает 1942-12-07 08:42:00
).
Вот запрос, который работает для каждого шестиминутного интервала.
SELECT DATE_FORMAT(datestamp,'%Y-%m-%d %H:00') +
INTERVAL (MINUTE(datestamp) -
MINUTE(datestamp) MOD 6) datestamp,
AVG(temp) temp
FROM measure
WHERE datestamp >= CURDATE() - INVERVAL 7 DAY
GROUP BY DATE_FORMAT(datestamp,'%Y-%m-%d %H:00') +
INTERVAL (MINUTE(datestamp) -
MINUTE(datestamp) MOD 6)
ORDER BY 1
При этом используется встроенная арифметика даты, а не арифметика метки времени unix.
Вы можете использовать сохраненную функцию, чтобы ее было легче читать.
DELIMITER $$
DROP FUNCTION IF EXISTS TRUNC_N_MINUTES$$
CREATE
FUNCTION TRUNC_N_MINUTES(datestamp DATETIME, n INT)
RETURNS DATETIME DETERMINISTIC NO SQL
COMMENT 'truncate to N minute boundary. For example,
TRUNCATE_N_MINUTES(sometime, 15) gives the nearest
preceding quarter hour'
RETURN DATE_FORMAT(datestamp,'%Y-%m-%d %H:00') +
INTERVAL (MINUTE(datestamp) -
MINUTE(datestamp) MOD n) MINUTE$$
DELIMITER ;
Тогда ваш запрос скажет
SELECT TRUNC_N_MINUTES(datestamp, 6) datestamp, AVG(temp) temp
FROM measure
WHERE datestamp >= CURDATE() - INVERVAL 7 DAY
GROUP BY TRUNC_N_MINUTES(datestamp, 6)
ORDER BY TRUNC_N_MINUTES(datestamp, 6)
Если вы хотите суммировать по 5, 10, 15 или минутным границам (три элемента в час), просто используйте это число вместо 6
.
Вам понадобятся различные функции trunc()
для часов и т. Д.
Функция trunc()
для ежедневных сводок - DATE(datestamp)
.
Для ежемесячных сводок это LAST_DAY(datestamp)
. Например,
SELECT LAST_DAY(datestamp) month_ending, AVG(temp) temp
FROM measure
GROUP BY LAST_DAY(datestamp)
ORDER BY LAST_DAY(datestamp)
дает ежемесячную сводку.