Sql 每两行的DATEDIFF之和(以分钟为单位)

Sql 每两行的DATEDIFF之和(以分钟为单位),sql,sql-server,sql-server-2008,datediff,Sql,Sql Server,Sql Server 2008,Datediff,我正在尝试对第三方员工时间跟踪数据库运行查询。据我所知,他们并没有对员工全天的工作时间进行统计。我拥有的是一系列包含用户ID和时间戳的行。如果我按时间戳对行进行排序,我可以有效地获得它们的穿孔历史。如果我假设第一个冲头在,第二个冲头在,第三个冲头在,等等,是否有一种有效的方法从每隔一行找到DATEDIFF(以分钟为单位),然后将它们相加,得到该员工一天的总时间 badge_no punch_timestamp 11209 1/31/14 7:58 AM 11209

我正在尝试对第三方员工时间跟踪数据库运行查询。据我所知,他们并没有对员工全天的工作时间进行统计。我拥有的是一系列包含用户ID和时间戳的行。如果我按时间戳对行进行排序,我可以有效地获得它们的穿孔历史。如果我假设第一个冲头在,第二个冲头在,第三个冲头在,等等,是否有一种有效的方法从每隔一行找到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分钟,我就看到了这篇帖子:


我先试试看

这里有一个相对简单、天真的方法。假设,如您所说,每个“奇数”行是一个戳入,每个“偶数”行是一个戳出,您可以分别获取奇数行和偶数行并计算每个工作块。请注意,我使用的
DateDiff
以分钟(
mi
)为单位,但您可以将其更改为小时/秒/任意值:

以下是我使用的测试数据:

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')

使用@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] 

最后总结每个徽章编号的时间:

SELECT [badge_no]
      ,SUM([Minutes])
FROM TimesPerBadge_No
GROUP BY [badge_no]

SELECT [badge_no]
      ,SUM([Minutes])
FROM TimesPerBadge_No
GROUP BY [badge_no]