MySQL 新手,需要帮助将表 1 中的用户数据处理成表 2 所示的结构。
表 1
表 2
用户 session 定义为至少每 30 分钟请求一次的用户事件期。当用户处于非事件状态超过 30 分钟时, session 结束。
有谁知道如何编写将表 1 转换为表 2 的 mysql 代码?
以下代码可用于创建日志表:
CREATE TABLE log
( user_id int, request_timestamp datetime);
INSERT INTO log
VALUES
(1, '2014-10-26 10:51:18'), (1, '2014-10-26 10:52:20'), (1, '2014-10-26 11:15:03'), (1, '2014-10-26 11:39:18'), (1, '2014-10-26 15:01:18'), (1, '2014-10-26 15:01:21'), (1, '2014-10-27 21:22:19'),
(2, '2014-10-15 12:19:01'), (2, '2014-10-15 12:19:12'), (2, '2014-10-15 12:19:45'), (2, '2014-10-15 12:20:03'), (2, '2014-10-17 14:55:13'), (2, '2014-10-17 14:55:19'),(2, '2014-10-17 14:55:22')
;
最佳答案
架构
CREATE TABLE log
( user_id int, request_timestamp datetime);
INSERT INTO log
VALUES
(1, '2014-10-26 10:51:18'), (1, '2014-10-26 10:52:20'), (1, '2014-10-26 11:15:03'), (1, '2014-10-26 11:39:18'), (1, '2014-10-26 15:01:18'), (1, '2014-10-26 15:01:21'), (1, '2014-10-27 21:22:19'),
(2, '2014-10-15 12:19:01'), (2, '2014-10-15 12:19:12'), (2, '2014-10-15 12:19:45'), (2, '2014-10-15 12:20:03'), (2, '2014-10-17 14:55:13'), (2, '2014-10-17 14:55:19'),(2, '2014-10-17 14:55:22');
首先,我们将给以下内容起个名字,只是为了形象化:
注意下面的 1800 表示 30 分钟 * 60 秒/分钟
Specimen A
-----
select l.user_id,l.request_timestamp,
@sessionnum :=
if((@curuser = user_id and TIME_TO_SEC(TIMEDIFF(request_timestamp,@theDt))>1800),@sessionnum + 1,
if(@curuser <> user_id,1,@sessionnum)) as sessionnum,
@curuser := user_id as v_curuser,
@theDt:=request_timestamp as v_theDt
from log l cross join
(select @curuser := '', @sessionnum := 0,@theDt:='') gibberish
order by l.user_id,l.request_timestamp
+---------+---------------------+------------+-----------+---------------------+
| user_id | request_timestamp | sessionnum | v_curuser | v_theDt |
+---------+---------------------+------------+-----------+---------------------+
| 1 | 2014-10-26 10:51:18 | 1 | 1 | 2014-10-26 10:51:18 |
| 1 | 2014-10-26 10:52:20 | 1 | 1 | 2014-10-26 10:52:20 |
| 1 | 2014-10-26 11:15:03 | 1 | 1 | 2014-10-26 11:15:03 |
| 1 | 2014-10-26 11:39:18 | 1 | 1 | 2014-10-26 11:39:18 |
| 1 | 2014-10-26 15:01:18 | 2 | 1 | 2014-10-26 15:01:18 |
| 1 | 2014-10-26 15:01:21 | 2 | 1 | 2014-10-26 15:01:21 |
| 1 | 2014-10-27 21:22:19 | 3 | 1 | 2014-10-27 21:22:19 |
| 2 | 2014-10-15 12:19:01 | 1 | 2 | 2014-10-15 12:19:01 |
| 2 | 2014-10-15 12:19:12 | 1 | 2 | 2014-10-15 12:19:12 |
| 2 | 2014-10-15 12:19:45 | 1 | 2 | 2014-10-15 12:19:45 |
| 2 | 2014-10-15 12:20:03 | 1 | 2 | 2014-10-15 12:20:03 |
| 2 | 2014-10-17 14:55:13 | 2 | 2 | 2014-10-17 14:55:13 |
| 2 | 2014-10-17 14:55:19 | 2 | 2 | 2014-10-17 14:55:19 |
| 2 | 2014-10-17 14:55:22 | 2 | 2 | 2014-10-17 14:55:22 |
+---------+---------------------+------------+-----------+---------------------+
如果您愿意,我们就完成了。但是对于 pretty-print ,可以将标本A
包裹在另一个里面:
select user_id,request_timestamp,sessionnum
from
( select l.user_id,l.request_timestamp,
@sessionnum :=
if((@curuser = user_id and TIME_TO_SEC(TIMEDIFF(request_timestamp,@theDt))>1800),@sessionnum + 1,
if(@curuser <> user_id,1,@sessionnum)) as sessionnum,
@curuser := user_id as v_curuser,
@theDt:=request_timestamp as v_theDt
from log l cross join
(select @curuser := '', @sessionnum := 0,@theDt:='') gibberish
order by l.user_id,l.request_timestamp
) SpecimenA
order by user_id,sessionnum
+---------+---------------------+------------+
| user_id | request_timestamp | sessionnum |
+---------+---------------------+------------+
| 1 | 2014-10-26 10:51:18 | 1 |
| 1 | 2014-10-26 10:52:20 | 1 |
| 1 | 2014-10-26 11:15:03 | 1 |
| 1 | 2014-10-26 11:39:18 | 1 |
| 1 | 2014-10-26 15:01:18 | 2 |
| 1 | 2014-10-26 15:01:21 | 2 |
| 1 | 2014-10-27 21:22:19 | 3 |
| 2 | 2014-10-15 12:19:01 | 1 |
| 2 | 2014-10-15 12:19:12 | 1 |
| 2 | 2014-10-15 12:19:45 | 1 |
| 2 | 2014-10-15 12:20:03 | 1 |
| 2 | 2014-10-17 14:55:13 | 2 |
| 2 | 2014-10-17 14:55:19 | 2 |
| 2 | 2014-10-17 14:55:22 | 2 |
+---------+---------------------+------------+
14 rows in set (0.02 sec)
注意 OP 对 session 的定义。这是一种不活动,而不是持续时间。
关于mysql - 在 MySQL 中操作用户数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32511243/