mysql - 如何检测 MySQL DATETIME 列中的连续小时数?

标签 mysql sql

我们有一个这样的表:

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/

相关文章:

mysql - 如何对 MySQL 中的另一个表进行 ORDER BY CALCULATED SUM

数据库 |使用不同的 WHERE 子句从 SUM 中减去 COUNT

php - 从表中选择每个 user_id 不同的所有列

mysql - MySQL 中何时使用单引号、双引号和反引号

sql - 使用Python时如何在SQL查询中使用空字符串

sql - 只选择第一个结果...有更好的方法吗?

mysql - SQLSTATE[42S02] : Base table or view not found: 1146 Table 'softwareproject.o_r_f_o_l_s' doesn't exist error in laravel

c# - MySQL - 从另一个表更新一个表

mysql - #1215 - 无法添加外键约束

mysql - 如何将 like 与特定模式一起使用?