【发布时间】:2019-03-04 20:00:10
【问题描述】:
假设您有一个可以跟踪页面浏览量的通用分析工具,并且您想要获取每个用户的第一个事件和最后一个事件之间的总时间。是否可以使用窗口功能?
这是示例数据:
CREATE TABLE `user_events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user` varchar(45) DEFAULT NULL,
`page` varchar(45) DEFAULT NULL,
`ts` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `user_events` VALUES
(1,'user1','home','2019-03-03 10:00:00'),
(2,'user2','home','2019-03-03 10:00:11'),
(3,'user1','about','2019-03-03 10:00:23'),
(4,'user1','contact','2019-03-03 10:00:47'),
(5,'user2','services','2019-03-03 10:01:04'),
(6,'user2','contact','2019-03-03 10:01:15'),
(7,'user1','home','2019-03-03 18:20:34'),
(8,'user1','services','2019-03-03 18:20:37');
这让我们开始:
mysql> select * from user_events;
+----+-------+----------+---------------------+
| id | user | page | ts |
+----+-------+----------+---------------------+
| 1 | user1 | home | 2019-03-03 10:00:00 |
| 2 | user2 | home | 2019-03-03 10:00:11 |
| 3 | user1 | about | 2019-03-03 10:00:23 |
| 4 | user1 | contact | 2019-03-03 10:00:47 |
| 5 | user2 | services | 2019-03-03 10:01:04 |
| 6 | user2 | contact | 2019-03-03 10:01:15 |
| 7 | user1 | home | 2019-03-03 18:20:34 |
| 8 | user1 | services | 2019-03-03 18:20:37 |
+----+-------+----------+---------------------+
这一切完成后我们预期的结果如下:
- user1 = 47 秒
- user2 = 64 秒
- user1 session2 = 3 秒
这会给我们平均 38 秒
有这个博客似乎使用 Postgres 作为示例 https://blog.jooq.org/2015/05/12/use-this-neat-window-function-trick-to-calculate-time-differences-in-a-time-series/ 博客的最后一部分提到使用“重置”来启动计时器,但是我在将 Postgres 转换为 MySQL 时遇到了困难
我从https://modern-sql.com/feature/filter遵循了 FILTER 的替代方案
mysql> SELECT
-> COUNT(CASE WHEN page = 'home' THEN 1 END) OVER (ORDER BY ts) c,
-> ts
-> FROM user_events;
+---+---------------------+
| c | ts |
+---+---------------------+
| 1 | 2019-03-03 10:00:00 |
| 2 | 2019-03-03 10:00:11 |
| 2 | 2019-03-03 10:00:23 |
| 2 | 2019-03-03 10:00:47 |
| 2 | 2019-03-03 10:01:04 |
| 2 | 2019-03-03 10:01:15 |
| 3 | 2019-03-03 18:20:34 |
| 3 | 2019-03-03 18:20:37 |
+---+---------------------+
但我显然需要某种分组,以便第二次用户主页访问不会重置第一次。
我也尝试了一个简单的最小值/最大值
mysql> select TIMEDIFF(max(ts),min(ts)) as session_length, user
-> from user_events
-> group by user;
+----------------+-------+
| session_length | user |
+----------------+-------+
| 08:20:37 | user1 |
| 00:01:04 | user2 |
+----------------+-------+
但我再次需要重置,这样 user1 的 2 个会话就不会被分组。
我是否可以尝试对给定数据进行处理,或者我是否需要另一个“session_id”(或类似的)列来帮助查询
【问题讨论】:
-
您将什么定义为每个用户的“第一个和最后一个事件”?您的问题并不清楚这一点,我可以想象多种定义方式。
-
...换句话说,定义“会话”
-
就本示例而言,会话在您访问“主页”页面时开始。 “主页”页面的前一个事件将成为最后一个事件。我意识到在现实世界中,用户可以在任何页面上开始,但是对于我们的应用程序,无论他们在应用程序中的哪个位置开始,我们总是有一个“开始”事件,我将其等同于“主页”页面。 @TimBiegeleisen