TSQL - DateTime difference between more than two rows

时间:2017-08-03 07:09:31

标签: sql-server sql-server-2008 tsql

I'm trying to find out how to calculate difference between multiple rows from one simple query. Here it is:

SELECT [DateTime],EmployeeId,ControlPointID,EventTypeID
FROM   [Events]
WHERE  Day([DateTime]) = 4
       AND Month([DateTime]) = 7
       AND Year([DateTime]) = 2017
       AND EmployeeId = 451
       AND ControlPointID IN ( 3, 6 )
       AND EventTypeID IN ( 1, 2 )
       ORDER BY [DateTime] 

Result:

    DateTime                  EmployeeId    ControlPointID  EventTypeID
    2017-07-04 11:32:10.000   451           6               1
    2017-07-04 16:07:00.000   451           3               2
    2017-07-04 16:42:50.000   451           6               1
    2017-07-04 20:04:10.000   451           3               2

I need to calculate difference between [DateTime] in minutes. EventTypeId = 1 means that Employee enters to the building and EventTypeId=2 means that Employee leaves. I can calculate difference between first Enter Event and last Leave Event. In this case it's 512 minutes. But, i have problem to calculate work time, when someone enters twice and leaves twice. It should be 477 minutes. Calculation should looks like this:

    DateDiff = (2017-07-04 16:07:00.000 - 2017-07-04 11:32:10.000) +
               (2017-07-04 20:04:10.000 - 2017-07-04 16:42:50.000)

Can you help me figure it out, please ?

2 个答案:

答案 0 :(得分:3)

鉴于建筑物入口,可以使用cross apply

完成该入口后的第一次离开
select entry.EmployeeId, entry.DateTime, exit.DateTime
from Events entry
  cross apply (select top 1 e.DateTime
               from Events e
               where e.EmployeeId = entry.EmployeeId
                 and e.DateTime > entry.DateTime
                 and e.EventTypeId = 2
               order by e.DateTime asc
              ) as exit
where entry.EventTypeId = 1

此时你只需要使用applicable T/SQL function来获得你想要的任何单位的差异(例如,在datediff(minute, entry.DateTime, exit.DateTime)的分钟内。

要获得所有差异的总和,只需求出差异:

select EmployeeId, sum(mins)
from (
    select entry.EmployeeId, entry.DateTime as EntryDateTime, exit.DateTime as ExitDateTime, datediff(minute, EntryDateTime, ExitDateTime) as mins
    from Events entry
      cross apply (select top 1 e.DateTime
                   from Events e
                   where e.EmployeeId = entry.EmployeeId
                     and e.DateTime > entry.DateTime
                     and e.EventTypeId = 2
                   order by e.DateTime asc
                  ) as exit
    where entry.EventTypeId = 1
) as input
group by EmployeeId

编辑:添加了总体总和(为了清晰起见,内部带有差异)

答案 1 :(得分:2)

这可以使用LAG窗口函数来完成,因为2008年我们不需要left join Row_Number来查找上一个条目

;WITH cte
     AS (SELECT Row_number()OVER(Partition by EmployeeID ORDER BY [DateTime]) rn,*
         FROM   Yourresult)
SELECT a.EmployeeID, 
       Sum(Datediff(minute, b.[DateTime], a.[DateTime]))
FROM   cte a
       LEFT JOIN cte b
              ON a.EmployeeID = b.EmployeeID 
             AND a.rn = b.rn + 1
WHERE  a.[EventTypeId] = 2 
GROUP BY a.EmployeeID

注意:这认为没有任何错误的打击。就像你的样本数据一样