MYSQL 计算行和组之间的时间作为会话
MYSQL calculate time between rows and group as sessions
我的数据是这样的;
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 分钟,它仍被视为同一会话的一部分。有任何想法吗?
这可能不完全正确,但按照这些思路应该可行...
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 |
+---------------------+---------------------+----------+
对我来说最简单的解决方案是使用脚本遍历 table 一次并构建输出 table,但如果这对您来说不可能,您可以使用嵌套查询,如下所示:
(假设一个模式:CREATE TABLE Table1 (`dt` datetime)
到 select session 的开头:
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;
选择 session 的结尾是类似的。
然后将其合并到 session 的 select 开头和 session 最早的结尾:
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;
注意边界条件(第一个,最后一个 session,session 只有一行,如您的示例所示)并调整代码。祝你好运。
我的数据是这样的;
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 分钟,它仍被视为同一会话的一部分。有任何想法吗?
这可能不完全正确,但按照这些思路应该可行...
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 |
+---------------------+---------------------+----------+
对我来说最简单的解决方案是使用脚本遍历 table 一次并构建输出 table,但如果这对您来说不可能,您可以使用嵌套查询,如下所示:
(假设一个模式:CREATE TABLE Table1 (`dt` datetime)
到 select session 的开头:
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;
选择 session 的结尾是类似的。
然后将其合并到 session 的 select 开头和 session 最早的结尾:
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;
注意边界条件(第一个,最后一个 session,session 只有一行,如您的示例所示)并调整代码。祝你好运。