Как объединить несколько временных интервалов

0

Допустим, у меня есть следующая таблица

| 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 или оба, оценивается.

Спасибо заранее.

  • 0
    Неправильно понял вопрос, извините
Теги:

2 ответа

2
Лучший ответ

Предположим, что ваша таблица имеет имя 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-запрос не сделает этого.

  • 0
    Работает отлично. Спасибо :)
0

Я опишу для вас решение (Brute Force):

  • Получите все ваши данные из базы данных в PHP (как есть)
  • Получить пустые массивы с интервалом в один час
  • Завершить все ваши данные и получить временную метку, где начался час для start (т.е. округлить start); получить количество часов между этой начальной точкой отсчета и ваши start и end values (как плавающие)
  • При извлечении этих данных должно быть довольно просто (несколько if и while), чтобы отделить вашу активность от часов и добавить их в массив из 2.
  • В этот момент у вас будут назначены все ваши данные, сгруппированные с интервалом в один час. Приступайте к необходимой обработке.

Я рекомендую strtotime при вычислении временных меток, потому что у вас есть стандартные форматы времени. Чтобы добавить один час к своему времени, вы можете использовать strtotime('+1 hour', $timestamp).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню