MySQL - 从日志表中选择的总活动时间

时间:2017-11-08 04:44:44

标签: mysql sql

我有用户connection/disconnection日志表:

id   user_id  timestamp         action 
1    8        2017-05-01 10:25  connect
2    8        2017-05-01 11:00  disconnect
3    8        2017-05-01 12:10  connect
3    15       2017-05-01 12:11  connect
3    8        2017-05-01 12:10  disconnect

我的问题是我可以选择user_id:8个活动时间,以小时为单位,例如: 2017-05-01

我尝试从connections时间较大的用户和left join用户中选择disconnect,然后连接时间并保留第一行

SELECT u.*,u2.* FROM `user_log` as u 
INNER JOIN  `user_log` as u2 ON u2.action = 'disconnect' 
AND u.user_id =   u2.user_id AND u.`timestamp` < u2.`timestamp`
WHERE u.action = 'connect'
GROUP BY u.id

似乎它正常工作,但我不确定它是否是最好的方法,也有用户连接05-01但未连接05-02时未涵盖的情况,因此这意味着我必须计算到05-01中午12点

3 个答案:

答案 0 :(得分:1)

我认为您可以使用此查询:

select `user_id`, `date`
    , sum(timestampdiff(minute,`connectTime`,`disconnectTime`)) `totalMinutes`
from (
    select `l`.`id`, `l`.`user_id`, date(`l`.`timestamp`) as `date` , `l`.`timestamp` as `connectTime`, `l`.`action`
        , coalesce( 
           /* finding first row of disconnect logs after this connect log */
           (select `li`.`timestamp`
            from `logs` as `li` 
            where `l`.`user_id`= `li`.`user_id`       /* user_id should be same */
              and `l`.`timestamp` < `li`.`timestamp`  /* disconnect time should be bigger than connect time */
              and `li`.`action` = 'disconnect'
            order by `l`.`timestamp`
            limit 1), 
            date_add(date_add(date(`l`.`timestamp`), interval 1 day), interval -1 minute)   /* calculate last minute of current date  */
        ) as `disconnectTime`
    from `logs` as `l`
    /* filter connect logs only */
    where `l`.`action` = 'connect') `t`
group by `user_id`, `date`;

MySQL Fiddle Demo

答案 1 :(得分:0)

select con.user_id,SEC_TO_TIME(sum(TIME_TO_SEC(timediff(dis.timestamp,con.timestamp))))timeinuse 
from(SELECT @a :=@a+1 as line,w.user_id,w.id,w.timestamp ,w.action
 from user_log w ,(select @a:= 0)l
  where    w.action = 'connect' order by w.user_id,w.timestamp)con inner join 
  (SELECT  @b:=@b+1 as line ,w.timestamp,w.user_id
from user_log w  ,(select @b:= 0)l where  w.action = 'disconnect' group by w.id,w.user_id 
order by w.user_id,w.timestamp)dis on con.line = dis.line and con.user_id =dis.user_id group by con.user_id;

答案 2 :(得分:0)

在@ shA.t和其他人的帮助下评论海报

我终于找到了这个问题的答案!

SELECT *, sum(timestampdiff(minute,`connect_timestamp`,`disconnect_timestamp`)) `totalMinutes` 
FROM (

    SELECT user_id, LEAST(start_date, second_date) AS connect_timestamp, GREATEST(start_date, second_date) AS disconnect_timestamp 
    FROM (

          SELECT l.id, l.user_id,`l`.`timestamp` AS start_date,
          (CASE
              WHEN l.action = 'connect' THEN (
                  coalesce( 

                     (select `li`.`timestamp`
                      from `logs` as `li` 
                      where `l`.`user_id`= `li`.`user_id`       
                        and `l`.`timestamp` < `li`.`timestamp`  
                        and DATE(`l`.`timestamp`) = DATE(`li`.`timestamp`)
                        and `li`.`action` = 'disconnect'
                      order by `l`.`timestamp`
                      limit 1), 
                      date_add(date_add(date(`l`.`timestamp`), interval 1 day), interval -1 minute)   
                  )
              )
              WHEN l.action = 'disconnect' THEN (
                  coalesce( 

                     (select `li`.`timestamp`
                      from `logs` as `li` 
                      where `l`.`user_id`= `li`.`user_id`       
                        and `l`.`timestamp` > `li`.`timestamp`
                        and DATE(`l`.`timestamp`) = DATE(`li`.`timestamp`)  
                        and `li`.`action` = 'connect'
                      order by `l`.`timestamp`
                      limit 1), 
                      date_add(date(`l`.`timestamp`), interval 0 minute)   
                  )
              )
          END) as second_date
          FROM `logs` as `l` 

   ) as t GROUP BY connect_timestamp

) as t2 GROUP BY user_id, DATE(connect_timestamp) 

MySQL Fiddle Demo