【问题标题】:How to combine several time spans如何组合多个时间跨度
【发布时间】:2011-04-22 14:24:49
【问题描述】:

可以说,我有下表

| 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 还是两者兼而有之。

谢谢你。

【问题讨论】:

    标签: mysql


    【解决方案1】:

    假设您的表名为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:002010-10-08 03:13:00,一个(不是那么)简单的 SQL 查询是行不通的。

    【讨论】:

      【解决方案2】:

      我将为您概述一个解决方案(蛮力):

      1. 将所有数据从数据库获取到 PHP(原样)
      2. 每隔一小时获取一个空数组
      3. 循环所有数据并获取start 小时开始的时间戳(即向下舍入start);获取计算的起始参考点与您的 startend values 之间的小时数(作为浮点数)
      4. 提取这些数据后,应该很容易(几个ifs 和一个while)将您的活动划分为小时并将它们从2 添加到数组中。
      5. 此时,您将分配的所有数据按一小时间隔分组。继续进行所需的处理。

      我建议在计算时间戳时使用 strtotime,因为您有标准时间格式。要增加一小时的时间,您可以使用strtotime('+1 hour', $timestamp)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-10
        • 2012-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-30
        • 1970-01-01
        相关资源
        最近更新 更多