我必须计算每个工作人员的轮班时间。
我编写了一个查询,从我们的OLTP系统获取数据并返回日期,人员及其登录注销时间。登录和注销时间是系统中的两个单独的事务,但我想在一行中登录和注销时间。请参阅下面的图像,我得到的输入和我想要的输出。请帮助写下查询以实现我的目标。
答案 0 :(得分:1)
您真正想要的是lag()
函数,但在SQL Server 2008中不可用。因此,您可以使用子查询来模拟它:
select i.day, i.staff, i.login,
(select top 1 logout
from input i2
where i2.staff = i.staff and
i2.day = i.day and
i2.login = cast(login as date) and
i2.logout >= i.login
order by i2.logout
) as LogOut
from input i
where logout = cast(logout as date)
逻辑logout = cast(logout as date)
旨在识别时间组件logout
为零的行。
这假设没有一个班次超过午夜。
编辑:
在SQL Server 2012中,您可以使用相同的查询。用lead()
替换它有点工作:
select day, staff, login, logout
from (select i.day, i.staff, thedate as login, which,
lead(thedate) over (partition by staff, day order by date) as LogOut
from (select i.day, i.staff,
(case when login = cast(login as date) then logout
else login
end) as thedate,
(case when login = cast(login as date) then 'logout'
else 'login'
end) as which
from input i
) i
) i
where which = 'login'
需要更多子查询。问题是您要比较两个字段中的日期,因此最里面的子查询将它们放在一个字段中('thedate'
)。下一个查找nextdate(当一行是登录时,它假定是注销,而最外面的只是选择登录行。
老实说,考虑到你的数据结构,我认为我更喜欢带有子查询的第一个版本。
答案 1 :(得分:0)
当我必须对数据进行非规范化时,我喜欢使用自联接。我在SQL Server 2012上测试过以下内容。(但是,一般方法应该适用于任何支持自联接的SQL RDBS,但是您必须根据具体情况修改DATETIME2数据类型和函数调用。)
数据:
DECLARE @t1 AS TABLE (
Day1 DATE
,Staff VARCHAR(3)
,Login DATETIME2
,Logout DATETIME2
);
INSERT INTO @t1
VALUES ('20130704', '123', '20130704 18:44:16.533', '20130704 00:00:00.000')
,('20130706', '456', '20130706 00:00:00.000', '20130706 01:10:12.000')
,('20130704', '123', '20130704 00:00:00.000', '20130704 20:24:16.553')
,('20130704', '123', '20130704 20:44:16.533', '20130704 00:00:00.000')
,('20130704', '123', '20130704 00:00:00.000', '20130704 22:54:16.553')
,('20130705', '456', '20130705 08:45:12.550', '20130705 00:00:00.000');
解决方案:
SELECT a.Day1, a.Staff, a.Login, MIN(b.Logout) AS Logout,
DateDiff(minute, a.login, MIN(b.logout)) AS Elapsed
FROM @t1 a join @t1 b
ON a.Staff = b.Staff AND a.Login < b.Logout AND CONVERT(TIME, a.Login) > '00:00:00.00'
GROUP BY a.Day1, a.Staff, a.Login;
附加说明:
DateDiff
的第一个参数更改为hour
。)@Gordon Linoff