Sql 查询计算工作时间

Sql 查询计算工作时间,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有一个查询,get的员工打卡上班/下班,并将他们分组为夜班,因此第一个记录是前一个晚上 此查询的结果如下所示 Name ID CardCode Telephone EndOverDay T Day DayNumber InDay Name Pen-005731 0042f55c 8 1 2015-11-02 19:42:12.000 2

我有一个查询,get的员工打卡上班/下班,并将他们分组为夜班,因此第一个记录是前一个晚上

此查询的结果如下所示

        Name    ID          CardCode Telephone  EndOverDay          T                   Day  DayNumber InDay
        Name    Pen-005731  0042f55c    8           1       2015-11-02 19:42:12.000 2015.11.02  42309   1
        Name    Pen-005731  0042f55c    8           1       2015-11-03 01:12:08.000 2015.11.03  42309   2
        Name    Pen-005731  0042f55c    8           1       2015-11-03 01:41:43.000 2015.11.03  42309   3
        Name    Pen-005731  0042f55c    8           1       2015-11-03 07:47:25.000 2015.11.03  42309   4
        Name    Pen-005731  0042f55c    8           1       2015-11-03 19:44:02.000 2015.11.03  42310   1
        Name    Pen-005731  0042f55c    8           1       2015-11-04 01:00:01.000 2015.11.04  42310   2
        Name    Pen-005731  0042f55c    8           1       2015-11-04 01:26:30.000 2015.11.04  42310   3
        Name    Pen-005731  0042f55c    8           1       2015-11-04 07:55:55.000 2015.11.04  42310   4
        Name    Pen-005731  0042f55c    8           1       2015-11-04 19:42:51.000 2015.11.04  42311   1
        Name    Pen-005731  0042f55c    8           1       2015-11-05 01:08:35.000 2015.11.05  42311   2
        Name    Pen-005731  0042f55c    8           1       2015-11-05 01:36:20.000 2015.11.05  42311   3
        Name    Pen-005731  0042f55c    8           1       2015-11-05 07:49:14.000 2015.11.05  42311   4
        Name    Pen-005731  0042f55c    8           1       2015-11-05 19:42:37.000 2015.11.05  42312   1
        Name    Pen-005731  0042f55c    8           1       2015-11-06 01:17:05.000 2015.11.06  42312   2
        Name    Pen-005731  0042f55c    8           1       2015-11-06 01:45:44.000 2015.11.06  42312   3
        Name    Pen-005731  0042f55c    8           1       2015-11-06 07:45:56.000 2015.11.06  42312   4
        Name    Pen-005731  0042f55c    8           1       2015-11-09 19:39:21.000 2015.11.09  42316   1
        Name    Pen-005731  0042f55c    8           1       2015-11-10 01:11:15.000 2015.11.10  42316   2
        Name    Pen-005731  0042f55c    8           1       2015-11-10 01:36:39.000 2015.11.10  42316   3
        Name    Pen-005731  0042f55c    8           1       2015-11-10 07:57:02.000 2015.11.10  42316   4
        Name    Pen-005731  0042f55c    8           1       2015-11-10 19:42:45.000 2015.11.10  42317   1
        Name    Pen-005731  0042f55c    8           1       2015-11-11 01:16:07.000 2015.11.11  42317   2
        Name    Pen-005731  0042f55c    8           1       2015-11-11 01:40:06.000 2015.11.11  42317   3
        Name    Pen-005731  0042f55c    8           1       2015-11-11 07:55:20.000 2015.11.11  42317   4
T是记录的时间日期 Inday是刷卡的顺序

我需要得到每个DayNumber的时间,所以对于DayNumber 42317

这将是第1天和第2天,然后是第3-4天,再加上总时间的Datediff

这是我到目前为止所拥有的

        WITH ByDays AS ( 
            SELECT     CHINA_VISION_PubPersonnel.Name, CHINA_VISION_PubPersonnel.ID, CHINA_VISION_PubCards.CardCode, CHINA_VISION_PubPersonnel.Telephone, ATDShiftDetail.EndOverDay, 
                                  CHINA_VISION_DorEvents.EventTM AS T, CONVERT(VARCHAR(10), CHINA_VISION_DorEvents.EventTM, 102) AS Day, 
                                  FLOOR(CONVERT(FLOAT, DATEADD(hour, 5, EventTM))) AS DayNumber,    
                                  ROW_NUMBER() OVER(PARTITION BY FLOOR(CONVERT(FLOAT,FLOOR(CONVERT(FLOAT, DATEADD(hour, 6, EventTM))))) ORDER BY FLOOR(CONVERT(FLOAT, DATEADD(hour, 5, EventTM)))) InDay  
            FROM         CHINA_VISION_PubCards INNER JOIN
                                  CHINA_VISION_PubPersonnel ON CHINA_VISION_PubCards.PubPersonnel_Ref = CHINA_VISION_PubPersonnel.Reference INNER JOIN
                                  CHINA_VISION_DorEvents ON CHINA_VISION_PubCards.CardCode = CHINA_VISION_DorEvents.CardCode INNER JOIN
                                  ATDShiftDetail ON RIGHT(CHINA_VISION_PubPersonnel.ID, 4) = ATDShiftDetail.Name
            WHERE     (CHINA_VISION_DorEvents.DorCtrls_Ref = '16') AND (CHINA_VISION_DorEvents.CardCode = '0042f55c') AND (CONVERT(Date, CHINA_VISION_DorEvents.EventTM) 
                                  > DATEADD(day,-10, GETDATE())) AND ATDShiftDetail.EndOverDay = '1'


                )
                , Diffs AS (            
                SELECT 
                    EvenRow.Day,EvenRow.DayNumber, OddRow.ID, OddRow.name , OddRow.CardCode , OddRow.Telephone ,EvenRow.EndOverDay ,
                    EvenRow.T ET, OddRow.T OT, OddRow.T-EvenRow.T Diff, 
                    DATEDIFF(S,EvenRow.T,OddRow.T) DiffSeconds -- difference in seconds
                FROM 
                    (SELECT BE.T, BE.Day, BE.InDay, BE.ID , BE.Name , Be.CardCode, BE.Telephone, BE.EndOverDay, BE.DayNumber
                     FROM ByDays BE) EvenRow -- Even rows
                INNER JOIN
                    (SELECT BO.T, BO.Day, BO.InDay , BO.ID , BO.Name , BO.CardCode, BO.Telephone, BO.EndOverDay
                     FROM ByDays BO) OddRow -- Odd rows
                ON EvenRow.InDay = OddRow.InDay +1 -- Join rows (1,2), (3,4) and so on
                   AND EvenRow.Day = OddRow.Day --  in the same day
                )


                SELECT
                    Name,
                    CardCode,
                    ID,
                    Telephone,
                    EndOverDay,
                    MIN(Day),
                    DayNumber,
                    SUM(DiffSeconds) Seconds, 
                    CONVERT(VARCHAR(8), 
                    (DATEADD(S, SUM(DiffSeconds), '1900-01-01T00:00:00')),
                    108) TotalHHMMSS -- The same, formatted as HH:MM:SS
                FROM Diffs GROUP BY DayNumber,  ID , CardCode, Name, Telephone,EndOverDay
                ORDER BY DayNumber  
这会产生这样的结果

        Name    CardCode          ID    Telephone   EndOverDay      Day  DayNumber  Seconds TotalHHMMSS
        Name    0042f55c    Pen-005731      8           1       2015.11.03  42309   42997   11:56:37
        Name    0042f55c    Pen-005731      8           1       2015.11.04  42310   42416   11:46:56
        Name    0042f55c    Pen-005731      8           1       2015.11.05  42311   42803   11:53:23
        Name    0042f55c    Pen-005731      8           1       2015.11.06  42312   -23331  17:31:09
        Name    0042f55c    Pen-005731      8           1       2015.11.10  42316   42343   11:45:43
        Name    0042f55c    Pen-005731      8           1       2015.11.11  42317   -23953  17:20:47
正如您所看到的,由于提供的数据的结果不正确,因此没有对正确的时间进行差异化处理

create table punch (
    Name nvarchar(50),
    Id nvarchar(50),
    CardCode nvarchar(50),
    TelephoneEnd int,
    OverDay int,
    T datetime,
    punchDate datetime,
    DayNumber int,
    InDay int )


insert into punch 
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-09 19:39:21.000', '2015.11.09',  42316,   1 union all
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-10 01:11:15.000', '2015.11.10',  42316,   2 union all
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-10 01:36:39.000', '2015.11.10',  42316,   3 union all
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-10 07:57:02.000', '2015.11.10',  42316,   4 union all
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-10 19:42:45.000', '2015.11.10',  42317,   1 union all
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-11 01:16:07.000', '2015.11.11',  42317,   2 union all
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-11 01:40:06.000', '2015.11.11',  42317,   3 union all
select 'Hame',    'Pen-005731',  '0042f55c',    8,           1,   '2015-11-11 07:55:20.000', '2015.11.11',  42317,   4 

select sum(x.minutesPunched)/60 as hoursWorked,
       sum(x.minutesPunched) % 60 as minutesWorked
  from (
        select datediff(mi, p2.T, p1.T) as minutesPunched
          from punch p1
          inner join punch p2 on p1.DayNumber = p2.DayNumber and p1.InDay = p2.InDay + 1
       ) x
通过删除2-3个AGG进行分组:

select sum(x.minutesPunched)/60 as hoursWorked,
       sum(x.minutesPunched) % 60 as minutesWorked,
       x.DayNumber
  from (
        select datediff(mi, p1.T, p2.T) as minutesPunched,
               p1.DayNumber
          from punch p1
          inner join punch p2 on p1.DayNumber = p2.DayNumber and p1.InDay = p2.InDay - 1
          where (p1.InDay + 1) % 2 = 0
       ) x
 group by x.DayNumber

您说过,您有一个查询,请与我们共享(使用相关的表和一些示例数据)。创建一个数据库也有助于我们更好地了解您的问题。在提问之前,请阅读并使用,以确保您的问题不是重复的。您获得此数据集并在InDay=InDay+1上加入自身。这会在同一行上显示日期时间。然后您只需对其进行datediff。允许您对表进行更改吗?InDay与打卡/打卡的关系毫无意义。如果有一个名为clockOut的额外时间列,然后将T重命名为clockIn,会容易得多。由于无法更改表格,数据来自刷卡系统嗨,谢谢,我认为这会起作用,但我每天需要一个单独的工作时间,而不是所有天的总和,我该怎么做?谢谢ewahner,还有一件事,比如说12小时的小步舞曲,这是当天的总时间,比如说1-4,不是1-2-3-4,因为2-3之间的时间不应该被计算,我怎么能解决这个问题呢?所以你说的是,打孔2和3之间的时间不应该被加总,5和6之间的时间等等…我想我明白了…leme给你一些其他的东西啊,准确地说,想象一下如果你刷卡说你的在,那是1,然后你再刷卡,所以你的离开,比如晚餐,2,然后3会回来,然后4会在一天结束时离开好吧,我更新了查询…现在应该对你有用了。我基本上是从连接的左侧移除双关语,所以它们只会在连接的右侧被考虑。这意味着奇数是双关语…偶数是双关语…在偶数也被认为是双关语之前。