Допустим, у меня есть следующая таблица
| start | end | activity
+---------------------+---------------------+---------
| 2010-07-26 09:10:00 | 2010-07-26 09:21:00 | 6
| 2010-07-26 09:35:00 | 2010-07-26 09:47:00 | 5
| 2010-07-26 10:05:00 | 2010-07-26 10:45:00 | 5
| 2010-07-26 10:50:00 | 2010-07-26 11:22:00 | 6
| 2010-07-26 13:15:00 | 2010-07-26 13:43:00 | 7
| 2010-07-26 14:12:00 | 2010-07-26 14:55:00 | 2
Я хочу объединить небольшие промежутки времени, получая средние минуты с активностью в час. Что-то вроде этого:
| start | minutes_activity | avg_activity
+---------------------+---------------------+---------
| 2010-07-26 09:00:00 | 42 | {avg value}
| 2010-07-26 10:00:00 | 50 | {avg value}
| 2010-07-26 11:00:00 | 22 | {avg value}
| 2010-07-26 13:00:00 | 28 | {avg value}
| 2010-07-26 14:00:00 | 43 | {avg value}
Обратите внимание, что некоторые записи могут иметь активность минут за два часа, т.е. 10:50:00 - 11:22:00. В этом случае 10 минут следует добавить в 10:00 и 22 минут до 11:00.
Решение, будь то MySql, PHP или оба, оценивается.
Спасибо заранее.
Предположим, что ваша таблица имеет имя records
и что ваши временные интервалы не охватывают более двух часов:
SELECT DISTINCT(CONCAT(date,' ',IF(LENGTH(hour)=1, CONCAT('0',hour), hour), ':00:00')) AS start,
SUM(minutes) AS minutes_activity,
FORMAT(avg(activity),0) AS avg_activity
FROM (
SELECT date, hour, minutes, activity
FROM (
SELECT DATE(start) AS date,
HOUR(ADDDATE(start, INTERVAL 1 HOUR)) AS hour,
IF(HOUR(start) < HOUR(end), MINUTE(end), 0) AS minutes,
activity AS activity
FROM records
HAVING minutes>0
) t1
UNION (
SELECT DATE(ADDDATE(start, INTERVAL 1 DAY)) AS date,
HOUR(ADDDATE(start, INTERVAL 1 HOUR)) AS hour,
IF(HOUR(start) > HOUR(end), MINUTE(end), 0) AS minutes,
activity AS activity
FROM records
HAVING minutes>0
AND hour=0
)
UNION (
SELECT DATE(start) AS date,
HOUR(start) AS hour,
IF(HOUR(start) < HOUR(end),
(60 - MINUTE(start)),
IF(
DATE(start) < DATE(end),
(60 - MINUTE(start)),
(MINUTE(end) - MINUTE(start))
)
) AS minutes,
activity AS activity
FROM records
)
ORDER BY date ASC, hour ASC) t2
GROUP BY CONCAT(date,' ',IF(LENGTH(hour)=1, CONCAT('0',hour), hour), ':00:00');
... однако, если у вас есть интервал, который идет от, например, 2010-10-08 01:30:00
до 2010-10-08 03:13:00
, простой (не такой) SQL-запрос не сделает этого.
Я опишу для вас решение (Brute Force):
start
(т.е. округлить start
); получить количество часов между этой начальной точкой отсчета и ваши start
и end values
(как плавающие)if
и while
), чтобы отделить вашу активность от часов и добавить их в массив из 2.Я рекомендую strtotime при вычислении временных меток, потому что у вас есть стандартные форматы времени. Чтобы добавить один час к своему времени, вы можете использовать strtotime('+1 hour', $timestamp)
.