mysql - 从签到日期列表中获取持续时间

标签 mysql database date window-functions gaps-and-islands

我有一个用户的签到日期列表。 如何计算连续 checkin 和 checkout 之间的持续时间。 如果未找到结帐,则将持续时间保留为 0

+----+-----------+---------------------+
| ID | isCheckIn |     DateChecked     |
+----+-----------+---------------------+
| 1  |     1     | 2019-10-08 10:22:15 | 
| 2  |     0     | 2019-10-08 10:24:30 | 
| 3  |     1     | 2019-10-08 10:27:01 | 
| 4  |     1     | 2019-10-08 10:31:44 | 
| 5  |     0     | 2019-10-08 10:50:56 | 
| 6  |     1     | 2019-10-09 09:24:09 | 
| 7  |     0     | 2019-10-09 09:35:59 | 
| 8  |     1     | 2019-10-09 10:04:26 | 
+----+-----------+---------------------+

我期待这样的事情(持续时间以分钟为单位)...

+---------------------+---------------------+----------+
|      CheckIn        |       CheckOut      | Duration |
+---------------------+---------------------+----------+
| 2019-10-08 10:22:15 | 2019-10-08 10:24:30 |    2     |
| 2019-10-08 10:27:01 |                     |    0     |
| 2019-10-08 10:31:44 | 2019-10-08 10:50:56 |    19    |
| 2019-10-09 09:24:09 | 2019-10-09 09:35:59 |    11    |
| 2019-10-09 10:04:26 |                     |    0     |
+---------------------+---------------------+----------+

我解决了获取列表、遍历它、创建几个日期并计算时差的问题,但我更喜欢在服务器端做更多事情。 有什么建议吗?非常感谢!!!!

最佳答案

在 MySQL 8.0 中,您可以使用 lead() 解决此问题:

select
    DateChecked CheckIn,
    case 
        when leadIsCheckIn = 0 then leadDateChecked 
    end CheckOut,
    case 
        when leadIsCheckIn = 0 then timestampdiff(minute, DateChecked, leadDateChecked) 
        else 0 
    end Duration
from (
    select
        DateChecked,
        isCheckIn ,
        lead(DateChecked) over(order by DateChecked) leadDateChecked,
        lead(isCheckIn) over(order by DateChecked) leadIsCheckIn
    from mytable
) x
where isCheckIn = 1
order by DateChecked 

Demo on DB Fiddle :

| CheckIn             | CheckOut            | Duration |
| ------------------- | ------------------- | -------- |
| 2019-10-08 10:22:15 | 2019-10-08 10:24:30 | 2        |
| 2019-10-08 10:27:01 |                     | 0        |
| 2019-10-08 10:31:44 | 2019-10-08 10:50:56 | 19       |
| 2019-10-09 09:24:09 | 2019-10-09 09:35:59 | 11       |
| 2019-10-09 10:04:26 |                     | 0        |

在早期版本中,您可以使用自左连接 和相关子查询上的不存在 条件来模拟lead():

select
    t.DateChecked CheckIn,
    tlead.DateChecked CheckOut,
    coalesce(timestampdiff(minute, t.DateChecked, tlead.DateChecked), 0) Duration
from mytable t
left join mytable tlead
    on tlead.DateChecked > t.DateChecked
    and tlead.isCheckIn = 0
    and not exists (
        select 1
        from mytable t1
        where 
            t1.DateChecked > t.DateChecked 
            and t1.DateChecked < tlead.DateChecked
    )
where t.isCheckIn = 1
order by t.DateChecked 

Demo on DB Fiddle :同上结果。

关于mysql - 从签到日期列表中获取持续时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58384937/

相关文章:

mysql - 合并各个表?

php - 处理数据库连接中的各种错误-有些不起作用?

加载innoDB数据库主页时phpMyAdmin非常慢

javascript - 在 Javascript 中过滤日期

date - 比较 LocalDate 与 apache ignite 中 LocalDateTime 的日期部分

php - 在不刷新页面的情况下形成验证码

mysql - 线程 "main"java.lang.IncompatibleClassChangeError : Found interface org. apache.hadoop.mapreduce.JobContext 中的异常,但类是预期的?

database - MongoDB - 查找多个字段不存在于另一个集合中的文档

php - 从数据库中获取最新条目

javascript - 为什么 JavaScript 日期在夏令时后不更新?