我们有一个这样的表:
DESCRIBE time_slots; id int(11) user_id int(11) start_time datetime
start_time
字段始终以小时为增量(例如 2013-09-04 16:00:00
)
我们的数据科学家希望以一种识别每个 user_id
连续 start_time
记录的方式查询该表,以便她可以创建一个如下所示的派生表:
id int(11) user_id int(11) start_time datetime end_time datetime
例如,给定以下数据:
user_id: 5, start_time: 2013-09-04 16:00:00 user_id: 5, start_time: 2013-09-04 17:00:00 user_id: 5, start_time: 2013-09-04 18:00:00 user_id: 6, start_time: 2013-09-04 16:00:00 user_id: 6, start_time: 2013-09-04 17:00:00 user_id: 6, start_time: 2013-09-04 18:00:00 user_id: 6, start_time: 2013-09-04 20:00:00 user_id: 6, start_time: 2013-09-04 21:00:00 user_id: 6, start_time: 2013-09-04 22:00:00
...我们可以得到这个输出:
user_id: 5, start_time: 2013-09-04 16:00:00, end_time: 2013-09-04 18:00:00 user_id: 6, start_time: 2013-09-04 16:00:00, end_time: 2013-09-04 18:00:00 user_id: 6, start_time: 2013-09-04 20:00:00, end_time: 2013-09-04 22:00:00
给定用户每天可能有多个这样的开始/结束“ block ”(但它们不会重叠)。
在执行 B 计划(设置非规范化数据仓库)之前,有什么想法可以在 SQL 中完成此操作吗?
最佳答案
根据您的数据库...窗口函数可以实现这一点。生成一列,表示与前一列的增量(因此您需要按 user_id、startTime 排序);然后,您可以使用该增量列进行分组。由于连续区 block 在增量中将用“1”表示,并且新区 block 将具有更高的数字。
您也可以通过与子查询进行连接并将其偏移 1 来实现此目的,例如在 ROW_NUMBER 和 ROW_NUMBER-1 上连接,然后您可以计算时间戳之间的增量,并使用外部选择来实现一些神奇的效果得到你想要的。关键是增量。
你可以这样做:
SET @prevUser := null;
SET @prevStartTime := 0;
SET @groupNumber := 1;
SET @groupPrevUser := null;
select
user,
groupNumber,
min(startTime),
max(endTime),
max(endTime) - min(startTime) as 'duration'
from
(SELECT
user,
startTime,
endTime,
delta,
IF(delta != 10000 || @groupPrevUser <> user, @groupNumber:=@groupNumber + 1, @groupNumber) 'groupNumber',
@groupPrevUser:=user
from
(SELECT
user,
startTime,
endTime,
IF(@prevUser <> user || @prevStartTime = 0, endTime - startTime, startTime - @prevStartTime) AS delta,
@prevUser:=user,
@prevStartTime:=startTime
FROM
queries
ORDER BY user , startTime) userData) userGroupData
group by user , groupNumber
得到这个结果:
# user, groupNumber, min(startTime), max(endTime), duration
bob, 1, 1392060000, 1392080000, 20000
bob, 2, 1392090000, 1392100000, 10000
jim, 3, 1392150000, 1392180000, 30000
使用此基表:
# user, startTime, endTime
bob, 1392060000, 1392070000
bob, 1392070000, 1392080000
bob, 1392090000, 1392100000
jim, 1392150000, 1392160000
jim, 1392160000, 1392170000
jim, 1392170000, 1392180000
关于mysql - 如何检测 MySQL DATETIME 列中的连续小时数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21891345/