MYSQL计算行和组之间的时间作为会话

时间:2015-01-01 16:00:42

标签: mysql datetime

我的数据看起来像这样;

datetime
2014-12-28 07:26:29
2014-12-28 07:25:29
2014-12-28 07:24:29
2014-12-28 07:23:30
2014-12-28 07:22:29
2014-12-28 00:19:49
2014-12-27 22:24:52 * end
2014-12-27 22:23:52
2014-12-27 22:22:52
2014-12-27 22:21:52
2014-12-27 22:20:52 * start

我希望输出像;

datetime_start         datetime_end             duration_in_mins
2014-12-28 07:22:29    2014-12-28 07:26:29      4
2014-12-28 00:19:49    2014-12-28 00:19:49      1
2014-12-27 22:20:52    2014-12-27 22:24:52      4

因此,如果下一行是在另一行之后1分钟,那么它仍然被认为是同一会话的一部分。有任何想法吗?

2 个答案:

答案 0 :(得分:1)

这可能不完全正确,但沿着这些方面应该有用......

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(datetime DATETIME NOT NULL PRIMARY KEY);


INSERT INTO my_table VALUES
('2014-12-28 07:26:29'),
('2014-12-28 07:25:29'),
('2014-12-28 07:24:29'),
('2014-12-28 07:23:30'),
('2014-12-28 07:22:29'),
('2014-12-28 00:19:49'),
('2014-12-27 22:24:52'),
('2014-12-27 22:23:52'),
('2014-12-27 22:22:52'),
('2014-12-27 22:21:52'),
('2014-12-27 22:20:52');

SELECT MIN(a.datetime) start
     , MAX(a.datetime) end
     , TIMEDIFF(MAX(a.datetime)+INTERVAL 1 MINUTE,MIN(a.datetime)) diff
  FROM
     ( SELECT x.* 
     , MAX(y.datetime) a
     , MAX(y.datetime) < x.datetime - INTERVAL 1 MINUTE session
  FROM my_table x 
  JOIN my_table y 
    ON y.datetime < x.datetime 
 GROUP
    BY x.datetime
     ) a
  JOIN (SELECT @session := 1) vars
GROUP BY CASE WHEN session = 1 THEN @session := @session + 1 ELSE @session := @session END;

+---------------------+---------------------+----------+
| start               | end                 | diff     |
+---------------------+---------------------+----------+
| 2014-12-27 22:21:52 | 2014-12-27 22:24:52 | 00:04:00 |
| 2014-12-28 00:19:49 | 2014-12-28 00:19:49 | 00:01:00 |
| 2014-12-28 07:22:29 | 2014-12-28 07:22:29 | 00:01:00 |
| 2014-12-28 07:23:30 | 2014-12-28 07:26:29 | 00:03:59 |
+---------------------+---------------------+----------+

答案 1 :(得分:0)

对我来说最简单的解决方案是使用脚本遍历表并构建输出表,但如果这对您不可行,则可以使用嵌套查询获得相同的结果,如下所示:

(假设架构:CREATE TABLE Table1 (`dt` datetime)

选择会话的开头:

SELECT dt AS s_start 
FROM Table1 start 
WHERE Timestampdiff(minute, (select max(dt) from Table1 m where m.dt < start.dt), start.dt ) > 1;

选择会话的结尾是类似的。

然后将其组合以选择最早结束会话的会话开头:

SELECT dt AS s_start,
(SELECT min(s_end_1) FROM
   (SELECT e_1.dt AS s_end_1 
   FROM Table1 e_1 
   WHERE Timestampdiff(minute, e_1.dt, (select min(dt) from Table1 t where t.dt > e_1.dt) ) > 1 ) e
 WHERE e.s_end_1 > start.dt) as s_end
FROM Table1 start 
WHERE Timestampdiff(minute, (select max(dt) from Table1 m where m.dt < start.dt), start.dt ) > 1;

注意边界条件(第一个,最后一个会话,在您的示例中仅包含单行的会话)并调整代码。祝你好运。