我正在尝试针对第三方员工时间跟踪数据库运行查询。据我所知,他们不会在一天的员工时间内保持总计。我所拥有的是一系列包含用户ID和时间戳的行。如果我按时间戳排序行,我会有效地获得他们的拳击历史。如果我假设冲头1在,冲头2出来,冲头3在等等,是否有一种有效的方法在几分钟内从每隔一行找到DATEDIFF,然后将它们相加以获得当天的总时间那个员工?
badge_no punch_timestamp
11209 1/31/14 7:58 AM
11209 1/31/14 9:57 AM
11209 1/31/14 10:00 AM
11209 1/31/14 10:07 AM
发布后不到2分钟,我发现了这篇帖子: SQL Server find datediff between different rows, sum
我先试试。
答案 0 :(得分:2)
这是一种相对简单,天真的做法。假设,就像你说的那样,每个“奇数”行都是一个标记,每个“偶数”行都是一个标记,你可以分别抓住奇数行和偶数行并计算每个工作块。请注意,我使用的DateDiff
是几分钟(mi
),但您可以将其更改为小时/秒/其他:http://technet.microsoft.com/en-us/library/ms189794.aspx
;WITH StartTime AS
(
SELECT
badge_no,
punch_timestamp,
myrow
FROM
(
SELECT
badge_no,
punch_timestamp,
ROW_NUMBER() OVER (Partition BY badge_no ORDER BY punch_timestamp ASC) as myrow
FROM #Time
) [t1]
WHERE myrow % 2 = 1 --odd rows
)
,EndTime AS
(
SELECT
badge_no,
punch_timestamp,
myrow - 1 as 'myrow' --Subtract 1 to match up with the odd rows
FROM
(
SELECT
badge_no,
punch_timestamp,
ROW_NUMBER() OVER (Partition BY badge_no ORDER BY punch_timestamp ASC) as myrow
FROM #Time
) [t1]
WHERE myrow % 2 = 0 --even rows
)
SELECT
badge_no,
SUM(diff) as 'MinutesWorked'
FROM
(
SELECT
EndTime.badge_no,
DATEDIFF(mi,
(SELECT TOP 1
punch_timestamp
FROM StartTime
WHERE StartTime.badge_no = EndTime.badge_no
AND StartTime.myrow = EndTime.myrow),
EndTime.punch_timestamp) as 'diff'
FROM EndTime
) [t1]
GROUP BY badge_no
以下是我使用的测试数据:
CREATE TABLE #Time
(
badge_no nvarchar(10),
punch_timestamp datetime
)
INSERT INTO #Time VALUES ('100', '2013-01-02 12:01 PM')
INSERT INTO #Time VALUES ('100', '2013-01-02 1:38 PM')
INSERT INTO #Time VALUES ('100', '2013-01-02 2:29 PM')
INSERT INTO #Time VALUES ('100', '2013-01-03 3:01 PM')
INSERT INTO #Time VALUES ('100', '2013-01-03 4:20 PM')
INSERT INTO #Time VALUES ('100', '2013-01-04 12:01 PM')
INSERT INTO #Time VALUES ('100', '2013-01-04 2:01 PM')
INSERT INTO #Time VALUES ('100', '2013-01-04 3:11 PM')
INSERT INTO #Time VALUES ('100', '2013-01-04 4:21 PM')
INSERT INTO #Time VALUES ('100', '2013-01-05 12:01 PM')
INSERT INTO #Time VALUES ('100', '2013-01-05 1:01 PM')
INSERT INTO #Time VALUES ('200', '2013-01-04 2:11 AM')
INSERT INTO #Time VALUES ('200', '2013-01-04 4:34 PM')
INSERT INTO #Time VALUES ('200', '2013-01-05 1:01 AM')
INSERT INTO #Time VALUES ('200', '2013-01-05 4:29 AM')
答案 1 :(得分:1)
使用@DaveZych样本数据我设法使用下面的SQL语句计算出与他相同的结果:
;WITH DataSource ([StartOrEnd], [badge_no], [punch_timestamp]) AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY [badge_no] ORDER BY [punch_timestamp]) +
ROW_NUMBER() OVER (PARTITION BY [badge_no] ORDER BY [punch_timestamp]) % 2
,[badge_no]
,[punch_timestamp]
FROM #Time
),
TimesPerBadge_No ([badge_no], [StartOrEnd], [Minutes]) AS
(
SELECT [badge_no]
,[StartOrEnd]
,DATEDIFF(MINUTE, MIN([punch_timestamp]), MAX([punch_timestamp]))
FROM DataSource
GROUP BY [badge_no]
,[StartOrEnd]
)
SELECT [badge_no]
,SUM([Minutes])
FROM TimesPerBadge_No
GROUP BY [badge_no]
这里可以看到每个CTE的值:
首先,我们需要对每个开始和结束日期进行分组:
SELECT ROW_NUMBER() OVER (PARTITION BY [badge_no] ORDER BY [punch_timestamp]) +
ROW_NUMBER() OVER (PARTITION BY [badge_no] ORDER BY [punch_timestamp]) % 2
,[badge_no]
,[punch_timestamp]
FROM #Time
现在,我们可以计算每组的分钟差异:
SELECT [badge_no]
,[StartOrEnd]
,DATEDIFF(MINUTE, MIN([punch_timestamp]), MAX([punch_timestamp]))
FROM DataSource
GROUP BY [badge_no]
,[StartOrEnd]
并最终sumarize每个badge_no的分钟数:
SELECT [badge_no]
,SUM([Minutes])
FROM TimesPerBadge_No
GROUP BY [badge_no]