SQL 服务器用多个 IN OUT 计算工作时间

SQL Server calculating working hours with multiple IN OUT

我有一个 table 带有来自传感器机器的员工考勤日志,员工可以在一天内有多个 IN & OUT 条目,我想计算一个雇员保持 IN 的小时数(总工作时间) 通过忽略超时 这两天一直在寻找这个解决方案,但无法获得所需的结果。

日志 Table 如下 (checkin_out_log)

╔════════╦═══════╦═════════════════════════╦════════════╗
║ emp_id ║ shift ║       check_time        ║ check_type ║
╠════════╬═══════╬═════════════════════════╬════════════╣
║      2 ║     1 ║ 2018-02-22 07:00:44.000 ║ C-IN       ║
║      2 ║     1 ║ 2018-02-22 13:00:35.000 ║ B-OUT      ║
║      2 ║     1 ║ 2018-02-22 13:30:46.000 ║ B-IN       ║
║      2 ║     5 ║ 2018-02-22 16:00:55.000 ║ C-OUT      ║
╚════════╩═══════╩═════════════════════════╩════════════╝

期望的输出是:

╔════════╦══════════╦═════════════════════════╦════════════╗
║ emp_id ║  IN Hrs  ║       Date              ║ OUT HRS    ║
╠════════╬══════════╬═════════════════════════╬════════════╣
║      2 ║ 08:30    ║ 2018-01-22              ║ 00:30      ║
╚════════╩══════════╩═════════════════════════╩════════════╝

Here is the data in query

Here is what I get in results with data shown in screenshot with your query, please guide whats wrong

假设 IN 和 OUT 总是成对的。

您可以使用 LEAD() window 函数获取下一个 check_time。并使用CASE WHEN条件判断是IN还是OUT时间

select  emp_id, 
        in_hrs = sum(in_mins) / 60.0, 
        check_date = convert(date, check_time), 
        out_hrs = sum(out_mins) / 60.0
from
(
    select  *, 
            in_mins = CASE  WHEN    check_type in ('C-IN', 'B-IN')
                            AND     LEAD(check_type) OVER (PARTITION BY emp_id ORDER BY check_time) in ('C-OUT', 'B-OUT')
                            THEN    DATEDIFF(MINUTE, 
                                             check_time, 
                                             LEAD(check_time) OVER (PARTITION BY emp_id ORDER BY check_time))
                            ELSE    0
                            END,
            out_mins= CASE  WHEN    check_type in ('C-OUT', 'B-OUT')
                            AND     LEAD(check_type) OVER (PARTITION BY emp_id ORDER BY check_time) in ('B-IN')
                            THEN    DATEDIFF(MINUTE, 
                                             check_time, 
                                             LEAD(check_time) OVER (PARTITION BY emp_id ORDER BY check_time))
                            ELSE    0
                            END
    from    checkin_out_log
) d
group by emp_id, convert(date, check_time)

编辑:添加条件以验证 IN 没有 OUT 的情况,反之亦然。 in/out 将被忽略,不计算。

添加的条件是

LEAD(check_type) OVER (PARTITION BY emp_id ORDER BY check_time) in ('C-OUT', 'B-OUT')