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')
我有一个 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')