MySql按小时查询

时间:2015-07-31 13:27:09

标签: mysql stored-procedures

我有一个由查询返回的表

+--------+------------------------+-------------------------+--------------+--------------+
| userid |  logintime             |  logouttime             | Download(KB) | Upload(KB)   |
+--------+------------------------+-------------------------+--------------+--------------+
| ma29   |  "2015-07-29 16:25:50" |  "2015-07-29 16:38:17"  |  86.6904     |  25.1328     |
| ma29   |  "2015-07-29 16:38:47" |  "2015-07-29 17:45:41"  |  920.2256    |  16005.5889  |
| ma29   |  "2015-07-29 17:47:32" |  "2015-07-29 17:54:09"  |  18.2939     |  10.9756     |
| ma29   |  "2015-07-29 17:54:38" |  "2015-07-29 17:56:31"  |  0.0000      |  0.0000      |
| ma29   |  "2015-07-29 17:56:39" |  "2015-07-29 18:16:53"  |  78.5596     |  57.5908     |
+--------+------------------------+-------------------------+--------------+--------------+

如何计算用户在给定时间范围内按小时计算的活动时间,如下所示:

例如:在2015-07-29 16:00到2015-07-30 11:00之间按小时搜索用户的活动时间:

+---------------+-------------------+
| Hours         | Active Time(secs) |
+---------------+-------------------+
| 2015-07-29 16 | 2020              | 
| 2015-07-29 17 | 3452              | 
| 2015-07-29 18 | 1013              | 
| ............. | ................. |
| ............. | ................. |
| ............. | ................. |
| ............. | ................. |
| 2015-07-30 09 | 0                 | 
| 2015-07-30 10 | 10                | 
+---------------+-------------------+

我被困住了。不知道如何开始这个解决方案。另一个查询或存储过程??

1 个答案:

答案 0 :(得分:1)

<强>计划

  1. 创建digits_v以生成序列
  2. 交叉加入3次,并应用10的幂来构造hours数字,直到999(如果这小于输入之间的最大差异,那么只需用另一个交叉连接和10的幂来扩展)
  3. 使用开始输入和allhours构建hours,直到达到结束输入
  4. 使用条件

    allhours加入会话
    date_add(allhours.hourstart, interval 1 hour) > s.logintime
    and allhours.hourstart < s.logouttime
    

    这将采用allhours小时内有效的记录。

  5. 在小时间隔内构造clamp_left和clamp_right。处理空值。
  6. 从clamp_left到clamp_right
  7. 的时间差

    <强>查询

    select hourstart, userid, sum(time_to_sec(timediff(clamp_right, clamp_left))) as active
    from
    (
      select 
      allhours.hourstart,
      s.userid,
      s.logintime,
      s.logouttime,
      case when s.logintime is null or (s.logintime < allhours.hourstart) 
           then allhours.hourstart
           else s.logintime
      end as clamp_left
      ,
      case when s.logouttime is null
           then allhours.hourstart
           when s.logouttime > date_add(allhours.hourstart, interval 1 HOUR)
           then date_add(allhours.hourstart, interval 1 HOUR)
           else s.logouttime
      end as clamp_right
      from
      (
        select date_add(str_to_date('2015-07-29 16:00', '%Y-%m-%d %H:%i'), 
                        interval a2.n * 100 + a1.n * 10 + a0.n HOUR) as hourstart
        from digits_v a2
        cross join digits_v a1
        cross join digits_v a0
      ) allhours
      left join sessions s
      on 
      (
        date_add(allhours.hourstart, interval 1 hour) > s.logintime
        and allhours.hourstart < s.logouttime
      )
      where hourstart < str_to_date('2015-07-30 11:00', '%Y-%m-%d %H:%i')
    ) q1
    group by hourstart, userid
    order by hourstart, userid
    ;
    

    <强>输出

    +------------------------+--------+--------+
    |       hourstart        | userid | active |
    +------------------------+--------+--------+
    | July, 29 2015 16:00:00 | ma29   |   2020 |
    | July, 29 2015 17:00:00 | ma29   |   3452 |
    | July, 29 2015 18:00:00 | ma29   |   1013 |
    | July, 29 2015 19:00:00 | (null) |      0 |
    | July, 29 2015 20:00:00 | (null) |      0 |
    | July, 29 2015 21:00:00 | (null) |      0 |
    | July, 29 2015 22:00:00 | (null) |      0 |
    | July, 29 2015 23:00:00 | (null) |      0 |
    | July, 30 2015 00:00:00 | (null) |      0 |
    | July, 30 2015 01:00:00 | (null) |      0 |
    | July, 30 2015 02:00:00 | (null) |      0 |
    | July, 30 2015 03:00:00 | (null) |      0 |
    | July, 30 2015 04:00:00 | (null) |      0 |
    | July, 30 2015 05:00:00 | (null) |      0 |
    | July, 30 2015 06:00:00 | (null) |      0 |
    | July, 30 2015 07:00:00 | (null) |      0 |
    | July, 30 2015 08:00:00 | (null) |      0 |
    | July, 30 2015 09:00:00 | (null) |      0 |
    | July, 30 2015 10:00:00 | (null) |      0 |
    +------------------------+--------+--------+
    

    <强> sqlfiddle