【问题标题】:SQl Server datediff across rows跨行的 SQL Server 日期差异
【发布时间】:2017-07-21 15:04:02
【问题描述】:

我进行了彻底的搜索,但无法找到另一篇文章来展示如何完成此操作。我试图找到一种简单的方法来计算两个日期之间的总小时数。我的桌子是这样的:

emp_num  | time                     | punch_type
399      | 2017-07-05 04:44:00.000  | 1
399      | 2017-07-05 14:30:00.000  | 2
399      | 2017-07-06 04:40:00.000  | 1
399      | 2017-07-06 13:31:00.000  | 2

punch_type 表示时钟输入=1,时钟输出=2。我想计算同一天两次出拳之间的时间差。然后将这些总数加在一起,得出 7/5 和 7/6 的总工时。

编辑:我忘了提到有时每天可能会有多次打卡。

关于如何完成的任何想法?

【问题讨论】:

  • 每天是否有过多组出拳?喜欢午餐时间吗?
  • 是的,只是为了澄清。

标签: sql sql-server


【解决方案1】:

这是一种方法

查找每天的工作时间

select emp_num,cast(time as date),datediff(hh,min(time),max(time))
from yourtable 
group by emp_num,cast(time as date)

获取 x 到 y 天之间的总小时数

select emp_num,sum(tot_hours)
from 
(
select emp_num,cast(time as date),datediff(hh,min(time),max(time)) as tot_hours
from yourtable 
Where time >= '2017-07-05' and time < dateadd(dd,1,'2017-07-06')
group by emp_num,cast(time as date)
) a
Group by emp_num

注意:这考虑到每天只有两次打孔,就像您的示例数据一样

【讨论】:

    【解决方案2】:

    您可以 PIVOT 表格为您提供正确的布局

    数据透视表文档:https://technet.microsoft.com/en-us/library/ms177410%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396

    您希望 PIVOT 表具有以下列:

    • Emp_num
    • 时钟输入
    • 打卡
    • Diff(现在计算为新签到和签出列之间的 datediff)

    您可以按员工和日期对最后一列求和,以获得问题的答案。

    【讨论】:

      【解决方案3】:
      CREATE TABLE times
      (
          emp_num    INT
        , [time]     DATETIME
        , punch_type TINYINT
      );
      
      INSERT INTO times
      VALUES (399, '2017-07-05 04:44:00.000', 1)
           , (399, '2017-07-05 14:30:00.000', 2)
           , (399, '2017-07-06 04:40:00.000', 1)
           , (399, '2017-07-06 13:31:00.000', 2);
      
      SELECT t1.emp_num
          , CAST(t1.time AS DATE) d
           , SUM(DATEDIFF(HOUR, t1.time, t2.time)) total_time
        FROM times t1
       OUTER APPLY
           (   SELECT TOP 1 t2.[time]
                 FROM times t2
                WHERE t2.emp_num = t1.emp_num AND t2.punch_type = 2 AND t2.time > t1.time
                ORDER BY t2.time
           )       t2
       WHERE punch_type = 1
       GROUP BY t1.emp_num, CAST(t1.time AS DATE);
      

      【讨论】:

        【解决方案4】:

        这应该会给你你正在寻找的结果......

        IF OBJECT_ID('tempdb..#TestData', 'U') IS NULL 
        BEGIN   -- DROP TABLE #TestData;
            CREATE TABLE #TestData (
                emp_num INT NOT NULL,
                [time] DATETIME NOT NULL,
                punch_type TINYINT NOT NULL 
                );
        
            INSERT #TestData (emp_num, [time], punch_type) VALUES
                (399, '2017-07-05 04:44:00.000', 1),
                (399, '2017-07-05 14:30:00.000', 2),
                (399, '2017-07-06 04:40:00.000', 1),
                (399, '2017-07-06 13:31:00.000', 2);
        END;
        
        --==============================================================
        
        WITH
            cte_AddRN AS (
                SELECT 
                    td.emp_num, td.time, td.punch_type, 
                    RN = ROW_NUMBER() OVER (PARTITION BY td.emp_num, td.punch_type ORDER BY td.time)
                FROM
                    #TestData td
                ),
            cte_PivotInOut AS (
                SELECT 
                    arn.emp_num,
                    PunchIn = MAX(CASE WHEN arn.punch_type = 1 THEN arn.time END),
                    PunchOut = MAX(CASE WHEN arn.punch_type = 2 THEN arn.time END)
                FROM
                    cte_AddRN arn
                GROUP BY
                    arn.emp_num,
                    arn.RN
                )
        SELECT 
            pio.emp_num, 
            TotalHours = ROUND(SUM(DATEDIFF(ss, pio.PunchIn, pio.PunchOut) / 3600.0), 2)
        FROM
            cte_PivotInOut pio
        GROUP BY
            pio.emp_num;
        

        【讨论】:

          【解决方案5】:

          来,试试这个

          SELECT a.[emp_num]                                    AS 'Employee Number',
                        CAST(a.[Time] AS DATE)                  AS 'Time',                          
                        DATEDIFF(hh , MIN(time), MAX(time))     AS 'Hours'
          FROM dbo.times                                                                               AS a
          GROUP BY a.[emp_num], CAST(a.[Time] AS DATE)
          

          【讨论】:

            猜你喜欢
            • 2018-05-09
            • 1970-01-01
            • 1970-01-01
            • 2023-03-08
            • 1970-01-01
            • 1970-01-01
            • 2022-08-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多