SQL - 奇数/偶数列到另一列之间的差异

时间:2014-06-19 09:52:35

标签: sql sql-server date datediff difference

我有一张表格,其中包含以下数据。

 Employee      TimeRegister1           TimeRegister2           TimeRegister3           TimeRegister4           
    77    2014-04-01 11:51:43.000 2014-04-01 14:03:52.000 2014-04-01 14:17:01.000 2014-04-01 16:01:12.000
    77    2014-04-03 09:48:33.000 2014-04-03 12:13:43.000 2014-04-03 12:22:27.000 2014-04-03 14:03:43.000
    181   2014-04-02 08:24:34.000 2014-04-02 13:01:10.000 2014-04-02 14:30:31.000 2014-04-02 18:04:04.000

我需要的是在另一列上写下每个员工每天从每对列(奇数减去偶数)之间的差异计算的总数。

在上面的示例中,对于Employee 77 and 2014-04-01,它应该在另一列上写下TimeRegister 2 - TimeRegister 1TimeRegister 4 - TimeRegister 3之间差异的总和。

应该输出这样的东西(秒是无关紧要的,只需要几小时/分钟):

 Employee      TimeRegister1           TimeRegister2           TimeRegister3           TimeRegister4              CALCULATEDCOL        
    77      2014-04-01 11:51:43.000 2014-04-01 14:03:52.000 2014-04-01 14:17:01.000 2014-04-01 16:01:12.000    2014-04-01 03:56:00.000

除了TimeRegister列最多可以达到30列(我只显示了4列但可能更多)所以我需要对每个奇数/偶数对进行有序计算,直到它用完列。

任何帮助我如何在SQL中实现这一点将不胜感激。感谢。

1 个答案:

答案 0 :(得分:0)

假设所提供的表是正确的(即不是30列),您可以通过DATEDIFF DateTimes,将差异加在一起,然后将它们添加回其中一个时间的基准日期来完成此操作(假设所有DateTime都在同一天)。您可以通过选择分钟作为差异/添加分辨率来消除秒数。要处理缺失的数据,每个ISNULL()配对都需要COALESCEIn / Out

SELECT Employee, TimeRegister1, TimeRegister2, TimeRegister3, TimeRegister4, 
       DATEADD(mi, ISNULL(DATEDIFF(mi, TimeRegister1, TimeRegister2), 0) 
                 + ISNULL(DATEDIFF(mi, TimeRegister3, TimeRegister4), 0),
               CAST(CAST(TimeRegister1 AS DATE) AS DATETIME)) 
       as CALCULATEDCOL        
FROM TimeRegister;

根据评论,最好将CALCULATEDCOL拆分为单独的日期和时间组件,因为根据情况,CALCULATEDCOL根本不代表某个时间点。

SqlFiddle here

如果您确实最多有30列,则需要对每对In/Out数据重复计算(并希望员工每天不超过15次!)。< / p>

修改
要从时钟输入/输出数据的原始表中执行此操作,假设方向是可获得的(否则数据接下来是无用的),并丢弃员工在同一天没有连续输入和输出的任何数据,怎么样:

WITH cte AS 
(
   SELECT Employee, 
          TimeRegister,
          Direction,
          CAST(TimeRegister AS DATE) AS TheDate,
          ROW_NUMBER() OVER (PARTITION BY Employee, CAST(TimeRegister AS DATE) 
                             ORDER BY TimeRegister ASC) AS Rnk
   FROM TimeRegister
)
SELECT 
   cur.Employee,
   DATEADD(mi, SUM(DATEDIFF(mi, cur.TimeRegister, nxt.TimeRegister)), 
           CAST(cur.TheDate AS DATETIME)) AS CALCULATEDCOL
   FROM cte cur
      INNER JOIN cte nxt
      ON cur.Employee = nxt.Employee 
         AND cur.TheDate = nxt.TheDate AND cur.Rnk + 1 = nxt.Rnk
   WHERE cur.Direction = 'I' AND nxt.Direction = 'O'
   GROUP BY cur.Employee, cur.TheDate;

SqlFiddle here