简体   繁体   English

计算每个用户登录之间的时间

[英]Calculating Time Between Logins Per User

I have a table that contains a unique ID, start time, end time and user ID, we'll call this table User_Logged_In where the start time is when the user is logged in and the end time is when they are logged out.我有一个包含唯一 ID、开始时间、结束时间和用户 ID 的表,我们将此表称为 User_Logged_In,其中开始时间是用户登录的时间,结束时间是用户注销的时间。

I'm trying to display the latest 5 calculated "time since last activity" times, in days/hours/minutes/seconds, grouped by individual users (user IDs) and ordered from most recent to oldest.我试图显示最新的 5 个计算的“自上次活动以来的时间”时间,以天/小时/分钟/秒为单位,按个人用户(用户 ID)分组并从最近到最旧排序。

User A may have 3 logins, user B may have 12 logins, user C may have 8 logins.用户 A 可能有 3 次登录,用户 B 可能有 12 次登录,用户 C 可能有 8 次登录。 For each user, I'm looking for the time offline between each login.对于每个用户,我正在寻找每次登录之间的离线时间。 Ordered by user, then start time DESC, I'd expect the most recent record for each user wouldn't have a value.按用户排序,然后开始时间 DESC,我希望每个用户的最新记录不会有值。

Example:例子:

+------+---------------------+---------------------+---------+
|  id  | starttime           | endtime             | user_id |
+------+---------------------+---------------------+---------+
|  35  | 2018-12-19 15:20:45 | 2018-12-19 19:21:06 | 1       |
|  22  | 2018-12-19 14:51:39 | 2018-12-19 21:56:40 | 1       |
|  11  | 2018-01-05 14:28:17 | 2018-01-05 21:30:42 | 1       |
|  97  | 2019-09-25 13:17:34 | 2019-09-25 23:31:31 | 2       |
|  86  | 2019-07-31 20:42:16 | 2019-07-31 22:42:38 | 2       |
|  72  | 2019-05-21 17:49:21 | 2019-05-21 20:03:03 | 2       |
|  83  | 2019-07-31 14:30:39 | 2019-07-31 20:30:58 | 3       |
|  79  | 2019-07-30 13:49:23 | 2019-07-30 23:59:01 | 3       |
|  61  | 2019-04-12 15:03:25 | 2019-04-13 01:54:23 | 3       |
|  54  | 2019-02-03 06:45:33 | 2019-02-03 17:33:48 | 3       |
|  51  | 2019-01-23 09:12:15 | 2019-01-29 14:44:38 | 3       |
+------+---------------------+---------------------+---------+

http://sqlfiddle.com/#!9/0dba46/2 http://sqlfiddle.com/#!9/0dba46/2

End Result:最终结果:

+----+---------------------+---------------------+-------------------------------------------+---------+
| id | starttime           | endtime             | difference                                | user_id |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 35 | 2018-12-19 15:20:45 | 2018-12-19 19:21:06 | -                                         | 1       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 22 | 2018-12-19 14:51:39 | 2018-12-19 21:56:40 | 0 Days, 6 Hours, 35 Minutes, 55 Seconds   | 1       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 11 | 2018-01-05 14:28:17 | 2018-01-05 21:30:42 | 347 Days, 17 Hours, 57 Minutes, 23 Seconds | 1       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 97 | 2019-09-25 13:17:34 | 2019-09-25 23:31:31 | -                                         | 2       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 86 | 2019-07-31 20:42:16 | 2019-07-31 22:42:38 | 55 Days, 14 Hours, 56 Minutes, 15 Seconds  | 2       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 72 | 2019-05-21 17:49:21 | 2019-05-21 20:03:03 | 71 Days, 0 Hours, 39 Minutes, 13 Seconds  | 2       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 83 | 2019-07-31 14:30:39 | 2019-07-31 20:30:58 | -                                         | 3       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 79 | 2019-07-30 13:49:23 | 2019-07-30 23:59:01 | 1 Days, 6 Hours, 41 Minutes, 35 Seconds   | 3       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 61 | 2019-04-12 15:03:25 | 2019-04-13 01:54:23 | 108 Days, 11 Hours, 55 Minutes, 0 Seconds | 3       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 54 | 2019-02-03 06:45:33 | 2019-02-03 17:33:48 | 67 Days, 21 Hours, 29 Minutes, 37 Seconds  | 3       |
+----+---------------------+---------------------+-------------------------------------------+---------+
| 51 | 2019-01-29 09:12:15 | 2019-01-23 14:44:38 | 10 Days, 16 Hours, 0 Minutes, 55 Seconds   | 3       |
+----+---------------------+---------------------+-------------------------------------------+---------+

This value will be a column in a larger set of data.该值将是更大数据集中的一列。 I've tried a number of different things, including joining back to the same table, but can't find a way of returning this value quickly, or at all.我尝试了很多不同的方法,包括重新连接到同一张表,但找不到快速或根本无法返回此值的方法。

Currently on MySQL v5.6.当前在 MySQL v5.6 上。

Having taken the code from your SQLFiddle link, I created an output that seems desired.从您的 SQLFiddle 链接中获取代码后,我创建了一个似乎需要的输出。 It all relies on the functions TIMESTAMPDIFF , SEC_TO_TIME and TIME_FORMAT , you may not need all the resulting columns, I have selected the difference in seconds just to have an intermediate result for the desired output.这一切都依赖于函数TIMESTAMPDIFFSEC_TO_TIMETIME_FORMAT ,您可能不需要所有结果列,我选择了以秒为单位的差异只是为了获得所需输出的中间结果。
The following query might meet the requirements:以下查询可能满足要求:

SELECT
  user_id AS User,
  starttime AS Start,
  endtime AS End,
  TIMESTAMPDIFF(SECOND, starttime, endtime) AS "Difference in seconds",
  CONCAT(
    FLOOR(TIME_FORMAT(SEC_TO_TIME(TIMESTAMPDIFF(SECOND, starttime, endtime)), '%H') / 24), ' days ',
      MOD(
        TIME_FORMAT(SEC_TO_TIME(TIMESTAMPDIFF(SECOND, starttime, endtime)), '%H'), 24), ' hours, ',
        TIME_FORMAT(SEC_TO_TIME(TIMESTAMPDIFF(SECOND, starttime, endtime)), '%i minutes and %s seconds'
      )
   ) AS "readable Difference"
FROM
  Table1

This will output the following in the mentioned fiddle-link:这将在提到的小提琴链接中输出以下内容:

User    Start                   End                     Difference in seconds   readable Difference
1       2018-12-19T15:20:45Z    2018-12-19T19:21:06Z    14421                   0 days 4 hours, 00 minutes and 21 seconds
1       2018-12-19T14:51:39Z    2018-12-19T21:56:40Z    25501                   0 days 7 hours, 05 minutes and 01 seconds
1       2018-01-05T14:28:17Z    2018-01-05T21:30:42Z    25345                   0 days 7 hours, 02 minutes and 25 seconds
2       2019-09-25T13:17:34Z    2019-09-25T23:31:31Z    36837                   0 days 10 hours, 13 minutes and 57 seconds
2       2019-07-31T20:42:16Z    2019-07-31T22:42:38Z    7222                    0 days 2 hours, 00 minutes and 22 seconds
2       2019-05-21T17:49:21Z    2019-05-21T20:03:03Z    8022                    0 days 2 hours, 13 minutes and 42 seconds
3       2019-07-31T14:30:39Z    2019-07-31T20:30:58Z    21619                   0 days 6 hours, 00 minutes and 19 seconds
3       2019-07-30T13:49:23Z    2019-07-30T23:59:01Z    36578                   0 days 10 hours, 09 minutes and 38 seconds
3       2019-04-12T15:03:25Z    2019-04-13T01:54:23Z    39058                   0 days 10 hours, 50 minutes and 58 seconds
3       2019-02-03T06:45:33Z    2019-02-03T17:33:48Z    38895                   0 days 10 hours, 48 minutes and 15 seconds
3       2019-01-29T09:12:15Z    2019-01-23T14:44:38Z    -498457                 -6 days -18 hours, -27 minutes and 37 seconds

As you can see, the last row of the results seems undesired due to invalid data.如您所见,由于数据无效,结果的最后一行似乎并不理想。

the solution to your question is to use window functions.您的问题的解决方案是使用窗口函数。 you need to compare the begin of each session with the end of each previous session which can be achieved using the lag or lead function which allow to access the preceeding or following row within a window.您需要将每个会话的开始与之前每个会话的结束进行比较,这可以使用滞后超前函数来实现,该函数允许访问窗口中的前一行或后一行。

to show only the last 5 logins of a user we use the row_number function to generate a row count for each window (the window spans across all records of the same userid) and use an outer select to filter it by values <= 5.为了仅显示用户的最后 5 次登录,我们使用row_number函数为每个窗口生成行计数(窗口跨越同一用户 ID 的所有记录)并使用外部选择按 <= 5 的值过滤它。

see the example below:请参阅下面的示例:

select *
from (
         select l.userid,
                l.starttime,
                l.endtime,
                datediff(starttime, lead(l.endtime, 1)
                                         over (partition by l.userid order by l.endtime desc)) date_difference,
                timediff(starttime, lead(l.endtime, 1)
                                         over (partition by l.userid order by l.endtime desc)) time_difference,
                row_number() over (partition by l.userid)                                      rn
         from User_Logged_In l
         order by l.userid desc, l.starttime desc
     ) x
where x.rn <= 5

this results in the following result:这导致以下结果:

结果

the date_format and time_format functions can be used to format the dates and times according to your needs. date_formattime_format函数可用于根据需要格式化日期和时间。

i used the following sql to create and fill the table:我使用以下 sql 来创建和填充表:

drop table if exists User_Logged_In;
create table User_Logged_In
(
    id        int      not null unique,
    starttime datetime not null,
    endtime   datetime not null,
    userid    int      not null
);

insert into User_Logged_In(id, starttime, endtime, userid)
values (5, '2018-12-19 15:20:45', '2018-12-19 19:21:06', 1);
insert into User_Logged_In(id, starttime, endtime, userid)
values (22, '2018-12-19 14:51:39', '2018-12-19 21:56:40', 1);
insert into User_Logged_In(id, starttime, endtime, userid)
values (11, '2018-01-05 14:28:17', '2018-01-05 21:30:42', 1);
insert into User_Logged_In(id, starttime, endtime, userid)
values (97, '2019-09-25 13:17:34', '2019-09-25 23:31:31', 2);
insert into User_Logged_In(id, starttime, endtime, userid)
values (86, '2019-07-31 20:42:16', '2019-07-31 22:42:38', 2);
insert into User_Logged_In(id, starttime, endtime, userid)
values (72, '2019-05-21 17:49:21', '2019-05-21 20:03:03', 2);
insert into User_Logged_In(id, starttime, endtime, userid)
values (83, '2019-07-31 14:30:39', '2019-07-31 20:30:58', 3);
insert into User_Logged_In(id, starttime, endtime, userid)
values (79, '2019-07-30 13:49:23', '2019-07-30 23:59:01', 3);
insert into User_Logged_In(id, starttime, endtime, userid)
values (61, '2019-04-12 15:03:25', '2019-04-13 01:54:23', 3);
insert into User_Logged_In(id, starttime, endtime, userid)
values (54, '2019-02-03 06:45:33', '2019-02-03 17:33:48', 3);
insert into User_Logged_In(id, starttime, endtime, userid)
values (51, '2019-01-29 09:12:15', '2019-01-23 14:44:38', 3);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM