Sql 如何计算用户在工作上花费的加班时间
我有两个SQL Server表employeeempid、empname和employee_movementsempid、MoveDatetime,我按日期时间存储来自指纹的员工操作,我想计算每个员工从下午3:30到第二天早上6:00的下班时间 所以如果我有这些数据 | EmpID | MoveDateTime | |-------|--------------------| | 1 | 01.01.2020 3:30pm | | 1 | 01.01.2020 5:30pm | | 1 | 01.01.2020 11:00pm | | 1 | 02.01.2020 02:30am | | 2 | 01.01.2020 4:00am | | 2 | 01.01.2020 10:15am | | 1 | 02.01.2020 4:00pm | | 1 | 02.01.2020 5:00pm | 我应该得到这个结果 | EmpID | Entrance | Departure | Actual_hours | |-------|--------------------|--------------------|--------------| | 1 | 01.01.2020 3:30PM | 01.01.2020 5:30PM | 2.00 | | 1 | 01.01.2020 11:00PM | 02.01.2020 2:30Am | 3.5 | | 2 | 01.01.2020 4:00AM | 01.01.2020 10:15PM | 7.25 | | 1 | 02.01.2020 04:00am | 02.01.2020 5:00am | 01.00 | 我试过这个密码Sql 如何计算用户在工作上花费的加班时间,sql,sql-server,datetime,date-arithmetic,Sql,Sql Server,Datetime,Date Arithmetic,我有两个SQL Server表employeeempid、empname和employee_movementsempid、MoveDatetime,我按日期时间存储来自指纹的员工操作,我想计算每个员工从下午3:30到第二天早上6:00的下班时间 所以如果我有这些数据 | EmpID | MoveDateTime | |-------|--------------------| | 1 | 01.01.2020 3:30pm | | 1 | 01.01.2020 5:
with cte as
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY [EmpID], cast ([MoveDateTime] as Date)
ORDER BY [MoveDateTime]) as rn
FROM employee_movements t1
)
SELECT c1.EmpID, c1.rn,c2.rn,
cast (c1.MoveDateTime as Date) as the_day,c1.MoveDateTime as enterance,c2.MoveDateTime as departure, cast (sum (DATEDIFF (S, c1.MoveDateTime, c2.MoveDateTime)/3600.00) as decimal(18,2)) as Actual_Hours
FROM cte c1
left JOIN cte c2
ON
c1.rn = c2.rn -1 AND
c1.EmpID = c2.EmpID and c1.rn % 2 <> 0
and (cast (c1.MoveDateTime as Date)=cast (c2.MoveDateTime as Date) ) or (c2.rn=1 and cast(dateadd(day,1,c1.MoveDateTime) as date)= cast(c2.MoveDateTime as Date) and (cast(c2.MoveDateTime as time) between '00:00:00' and '06:00:00'))
AND c2.rn % 2 = 0
where c2.rn is not null
GROUP BY c1.EmpID,c1.rn,c2.rn,
cast (c1.MoveDateTime as Date) ,c1.MoveDateTime,c2.MoveDateTime
我从中了解到每个员工的进出和工作时间,但按一天划分的问题不会返回第二个案例,因为员工仍在工作,第二天就离开了
感谢您的帮助。首先,您可以使用窗口函数交错行以生成输入/输出对:
select *
from (
select empid, movedatetime as dt_in,
lead(movedatetime) over(partition by empid order by movedatetime) as dt_out,
row_number() over(partition by empid order by movedatetime) rn
from employee_movements
) t
where rn % 2 = 1
然后我们需要计算每个日期范围的加班时间。SQL Server在日期算法方面不是很好;如果您没有太多的行同时进行,最简单的方法可能是暴力:枚举两个日期之间的所有分钟数,只计算不属于工作时间的分钟数
因此:
:
请以表格形式提供样本数据和预期结果。加班时间从下午3:30开始,到第二天早上6:00结束。我想按天计算员工每次指纹操作之间的所有时间。谢谢GMB,干得好,但有一点遗漏了,那就是2020-10-13和2020-10-21中的dt_和dt_out,跨越了不止一天,但我只想计算从第一天15:30开始到第二天6:00(最大值)的运动的加班时间,并排除这两天中dt_out为空的奇怪动作interval@hussein.nagdy例如我不知道你在说什么。您所引用的数据不是示例数据的一部分,是吗?事实上,它不在示例数据中,但在我的数据库中,它与me@hussein.nagdy:这是我的观点。。。此查询适用于您提供的示例数据。如果您有一个不同的用例,那么您可能想问一个新问题,提供适当的样本数据和期望的结果。
with
data as (
select empid, movedatetime as dt_in,
lead(movedatetime) over(partition by empid order by movedatetime) as dt_out,
row_number() over(partition by empid order by movedatetime) rn
from employee_movements
),
cte as (
select empid, dt_in, dt_out, dt_in as dt
from data
where rn % 2 = 1
union all
select empid, dt_in, dt_out, dateadd(minute, 1, dt)
from cte
where dateadd(minute, 1, dt) < dt_out
)
select empid, dt_in, dt_out,
sum(
case when convert(time, dt) >= '06:00:00' and convert(time, dt) < '15:30:00'
then 0
else 1
end) ot_minutes
from cte
group by empid, dt_in, dt_out
order by empid, dt_in
option (maxrecursion 0)
empid | dt_in | dt_out | ot_minutes
----: | :---------------------- | :---------------------- | ---------:
1 | 2020-01-01 15:30:00.000 | 2020-01-01 17:30:00.000 | 120
1 | 2020-01-01 23:00:00.000 | 2020-01-02 02:30:00.000 | 210
1 | 2020-01-02 16:00:00.000 | 2020-01-02 17:00:00.000 | 60
2 | 2020-01-01 04:00:00.000 | 2020-01-01 22:15:00.000 | 525