我有一个XYZ表,其中包含TIME数据类型列中的员工登录持续时间详细信息。
EmployeeID | DomainID | LoginDuration
----------------------------------------------------------------
1111 12 02:32:55:0000000
1111 4 00:57:17.0000000
1111 12 01:06:25.0000000
1111 11 03:31:23.0000000
2222 11 02:42:17.0000000
2222 4 03:54:52.0000000
2222 10 04:08:29.0000000
除上述列外,我还有LoginTimeStamp
和LoginWeek
列,我在JOIN语句中使用这些列。
我正在尝试获取LoginDuration
列的运行总计,如下所示:
EmployeeID | DomainID | HoursBefore | LoginDuration | HoursAfter |
---------------------------------------------------------------------------------
1111 12 00:00:00.0000000 02:32:55:0000000 **00:00:00.0000000**
1111 4 02:32:55.0000000 00:57:17.0000000 03:30:12.0000000
1111 12 03:30:12.0000000 01:06:25.0000000 04:36:37.0000000
1111 11 04:36:37.0000000 03:31:23.0000000 08:08:00.0000000
2222 11 00:00:00.0000000 02:42:17.0000000 **00:00:00.0000000**
2222 4 01:32:31.0000000 03:54:52.0000000 04:14:48.0000000
2222 10 04:14:48.0000000 04:08:29.0000000 08:09:40.0000000
HoursBefore是HoursAfter的先前值(每位员工的第一行00:00:00)
HoursAfter = HoursBefore + LoginDuration
为此,我编写了以下查询,但是我收到了HoursAfter
列的错误。它并没有将每个员工的当前值和先前值相加。
SELECT
a.EmployeeID,a.LoginDuration,
COALESCE(CAST(
DATEADD(ms,
SUM(DATEDIFF(ms,0,CAST(b.LoginDuration as datetime)))
, 0)
as time)
,'00:00:00') AS HoursBefore,
a.LoginDuration as Hours,
COALESCE(CAST(
DATEADD(ms,
SUM(DATEDIFF(ms,0,CAST(b.LoginDuration as datetime)))
, a.Loginduration)
as time)
,'00:00:00') As HoursAfter
FROM XYZ AS a
LEFT OUTER JOIN XYZ AS b
ON (a.EmployeeID = b.EmployeeID)
AND (a.LoginWeek = b.LoginWeek)
AND (b.LoginTimeStamp < a.LoginTimeStamp)
GROUP BY a.EmployeeID, a.LoginTimeStamp,a.LoginDuration
ORDER BY a.LoginWeek, a.EmployeeID, a.LoginTimeStamp;
我需要查询帮助,以便每个员工的HoursAfter
列都合适。
非常感谢任何帮助。 (这是我的第一个查询,如果您可能需要任何进一步的细节,请回复。)
感谢。
答案 0 :(得分:0)
可惜SQL Server不支持句点数据类型,它会使数学变得更加简单。
但是,它在新版本中对窗口函数有相当好的支持,我们可以用它来解决这个问题:
declare @t table (ID int, EmployeeID int, DomainID int, LoginDuration time)
insert @t
values
(1, 1111, 12, '02:32:55.0000000'),
(2, 1111, 4, '00:57:17.0000000'),
(3, 1111, 12, '01:06:25.0000000'),
(4, 1111, 11, '03:31:23.0000000'),
(5, 2222, 11, '02:42:17.0000000'),
(6, 2222, 4, '03:54:52.0000000'),
(7, 2222, 10, '04:08:29.0000000')
;with x as (
select *, dateadd(second, sum(datediff(second, 0, loginduration)) over (partition by employeeid order by id), 0) sum_duration_sec,
row_number() over (partition by employeeid order by id) rn
from @t
)
select
employeeid,
domainid,
convert(time, isnull(lag(sum_duration_sec) over (partition by employeeid order by id),0)) hoursbefore,
loginduration,
convert(time, case when rn = 1 then 0 else sum_duration_sec end) hoursafter
from x
我为了简洁而引入了ID列以建立序列,您可能希望使用(LoginWeek,LoginTimestamp)来排序。
另外,不确定在第1行和第5行中HoursAfter应为0的要求 - 如果不是,则完全删除row_number()。
答案 1 :(得分:-1)
使用OUTER APPLY计算After Hours。之前的小时数是减去当前持续时间后的小时数
SELECT a.EmployeeID, a.DomainID,
HoursBefore = CONVERT(TIME, DATEADD(SECOND, b.after_secs - DATEDIFF(SECOND, 0, a.LoginDuration), 0)),
a.LoginDuration,
HoursAfter = CONVERT(TIME, DATEADD(SECOND, b.after_secs, 0))
FROM XYZ AS a
OUTER APPLY
(
SELECT after_secs = SUM(DATEDIFF(SECOND, 0, x.LoginDuration))
FROM XYZ x
WHERE x.EmployeeID = a.EmployeeID
AND x.LoginWeek = a.LoginWeek
AND x.LoginTimeStamp <= a.LoginTimeStamp
) b