在sql中找到同一个表中两个连续行之间的时间差

时间:2014-09-30 23:33:36

标签: sql sql-server sql-server-2008 ssms

我被困住了。我已经找到了答案,但似乎无法从相同表格的两个不同行中找到相同表格中的减去时间。我在以下查询中遇到困难。在下表中,我想将TimeOut从一行区分到下一行的TimeIn。请在下表中查看第1行(上午10点35分)的TimeOut和第2行(上午10点38分)的TimeIn之间的分钟差异。

表1:TIMESHEET

ROW    EmpID       TimeIn                   TimeOut
----------------------------------------------------------------
1       138         2014-01-05 10:04:00      2014-01-05 10:35:00   
2       138         2014-01-05 10:38:00      2014-01-05 10:59:00 
3       138         2014-01-05 11:05:00      2014-01-05 11:30:00  

预期结果

ROW    EmpID       TimeIn                   TimeOut                  Minutes
----------------------------------------------------------------------------
1       138         2014-01-05 10:04:00      2014-01-05 10:35:00       
2       138         2014-01-05 10:38:00      2014-01-05 10:59:00       3
3       138         2014-01-05 11:05:00      2014-01-05 11:30:00       6
etc
etc
etc

基本上,我需要区分查询中的时间,以显示员工休息的时间。

我已经尝试过加入,但这似乎不起作用,我不知道OVER PARTITION是否可行,因为我似乎无法遵循逻辑(是的,我还在学习)。我还考虑了两个临时表并对它们进行了比较,但是当我开始更改日期或员工ID时,这并不起作用。最后,我想在LEAD声明中可能OVER?或者使用DATEDIFF

进行CAST只是很简单

5 个答案:

答案 0 :(得分:3)

尝试类似的事情:

select *, DATEDIFF(minute, (
    select max(b.TimeOut)
    from TIMESHEET as b where a.EmpID=b.EmpID and b.ROW<a.ROW
    ), a.TimeIn
) as diff
from TIMESHEET as a

答案 1 :(得分:2)

我已经针对类似的问题解决了这个问题,并且不需要对行进行排序:

select t1.EmpID, t1.TimeIn, t1.TimeOut, 
       datediff(minute, max(t2.TimeOut), t1.TimeIn) as minutes
from timesheet t1 left join timesheet t2 on t1.EmpID = t2.EmpID 
       and t2.TimeOut < t1.TimeIn
group by t1.EmpID, t1.TimeIn, t1.TimeOut

让我知道这是否有效。

这是一个sql小提琴:http://sqlfiddle.com/#!3/89a43/1

答案 2 :(得分:1)

由于你已经提到了PARTITION子句,下面给出的是一个使用该子句的版本(没有经过语法测试,但它应该给你一个想法)

;WITH EmpData AS
(
    SELECT  EmpID, 
                TimeIn, 
                TimeOut,
                ROW_NUMBER() OVER(PARTITION BY EmpId ORDER BY TimeIn) Position
       FROM EmployeeTime 
)
SELECT a.*
         a.TimeOut-b.TimeIn OutTIme 
   FROM EmpData a  LEFT JOIN EmpData b
         ON a.EmpId = b.EmpId
      AND a.Position-1  = b.Position  

答案 3 :(得分:1)

WITH rows AS

(

SELECT  *, ROW_NUMBER() OVER (ORDER BY EmpID) AS rn        
FROM    TimeSheet         
)

SELECT mc.EmpID, DATEDIFF(MINUTE, mc.TimeIn, mp.TimeOut) as TimeDiffInMinutes
FROM    rows mc JOIN    rows mp ON   mc.rn = mp.rn-1

答案 4 :(得分:0)

循环游标通常是一种从性能角度和可证明性和可维护性两方面做事的惨淡方式,在这样的情况下,你在遍历有向非循环图的边缘,循环可以是正是医生所要求的。

在我看来,当使用不支持LEAD OVER PARTITION的SQL Server版本时,你有两个不错的选择。

  • 在T-SQL中使用游标循环
  • 使用应用程序代码中可枚举的LINQ进行循环

是否值得为LINQ的所有生命支持进行编组取决于你还在做什么。

问题是标记为sql-server-2008,它支持LEAD OVER PARTITION,并且在没有支持索引的情况下在该平台上,它的工作集要小得多,速度要快得多使用光标。