计算SQL Server中的多个班次时差

时间:2018-01-20 07:09:29

标签: sql-server sql-server-2012

我对SQL Server有疑问。请告诉我如何根据条件解决SQL Server中的登录和注销时间计算。

  1. 如果相同的empid可以多班次,同一日期的多班次计算必须是时差为5小时,然后该日期视为该emp的多班次
  2. OnFloor时间他花了多少时间
  3. OffFloor时间他花了多少时间
  4. 如果错过退出,则认为taligate为1或-1
  5. 示例输入数据:

    CREATE TABLE [dbo].[emplogindetails]
    (
        [Emp ID] [float] NULL,
        [Area Of Access] [nvarchar](255) NULL,
        [Time] [datetime] NULL
    ) ON [PRIMARY]
    GO
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-02T09:00:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-02T10:30:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-03T09:30:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-03T12:30:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-03T12:40:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-03T17:10:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-03T06:30:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-03T08:30:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-05T23:30:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-06T01:55:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-06T02:15:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-06T06:10:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-02T11:00:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-02T12:00:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-02T13:00:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-06T14:01:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-06T15:01:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4F White Rm IN', CAST(N'2017-08-06T15:20:00.000' AS DateTime))
    
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) 
    VALUES (1, N'K4FWhite Rm OUT', CAST(N'2017-08-06T20:01:00.000' AS DateTime))
    GO
    

    根据以上数据,第4个日期是假日,他进入第5个日期夜班,退出第6个日期和第6个日期,他又做了另一个班次。

    我想要一个如下输出:

    ShiftDate   |ShitStartTime              |ShiftEndTime               |Total_Time |OnFloor    |OffFloor   |EmpID  |Incount     |OutCount  |Tailgate
    08/05/2017  |2017-08-05 23:30:00.000    |2017-08-06 06:10:00.000    |6:40:00    |06:00:00   |00:40:00   |1      |2           |   2      |   0
    08/02/2017  |2017-08-02 09:00:00.000    |2017-08-02 13:00:00.000    |04:00:00   |02:30:00   |01:30:00   |1      |3           |   2      |   1
    08/03/2017  |2017-08-03 06:30:00.000    |2017-08-03 17:10:00.000    |10:40:00   |09:30:00   |01:10:00   |1      |3           |   3      |   0
    08/06/2017  |2017-08-06 14:01:00.000    |2017-08-06 20:01:00.000    |6:00:00    |05:10:00   |00:50:00   |1      |2           |   2      |   0
    

    我试过这样:

    select
      isnull( ShiftDate ,'1900-01-01')as ShiftDate , 
      isnull( min(logintime) ,'1900-01-01') as ShitStartTime,
       max( case when   logouttime is null  then '1900-01-01' else logouttime  end  )ShiftEndTime ,
    
     convert(varchar(8),dateadd(ss,sum(datediff(second,0,dateadd(day,0,Total_Time))),0),108) Total_Time,
      convert(varchar(8),dateadd(ss,sum(datediff(second,0,dateadd(day,0,OnFloor))),0),108) OnFloor,
    
      convert(varchar(8),dateadd(ss,sum(datediff(second,0,dateadd(day,0,OffFloor))),0),108) OffFloor,
    
     EmpID ,Incount ,OutCount, Tailgate
      from ( 
    select 
    CONVERT(VARCHAR(12), (  OffFloor  +  cast ( OnFloor as int)) / 60 / 60 % 24) 
     +':'+ CONVERT(VARCHAR(2), (OffFloor +  cast ( OnFloor as int)) / 60 % 60)
     +':'+ CONVERT(VARCHAR(2), (OffFloor +  cast ( OnFloor as int))  % 60) as Total_Time 
    ,case when convert( varchar(10),OnFloor )='0' then '0:0:0' else OnFloor end OnFloor
    ,  CONVERT(VARCHAR(12), (OffFloor) / 60 / 60 % 24)  +':'+ CONVERT(VARCHAR(2), (OffFloor) / 60 % 60) 
    +':'+ CONVERT(VARCHAR(2), (OffFloor)  % 60) AS OffFloor
      ,[Emp ID] ,[Area Of Access],status,logintime,logouttime 
    from ( 
    select    isnull( DATEDIFF(SECOND, a.logintime, a.logouttime) ,0) OffFloor , cast ( '0' as varchar) as OnFloor
    ,[Emp ID] ,[Area Of Access],status,logintime,logouttime 
     from ( 
     SELECT o.time logouttime,i.Time logintime,i.[Emp ID] 
    ,substring ( i.[Area Of Access] ,charindex('out',i.[Area Of Access]),len(i.[Area Of Access])) status
                  ,i.[Area Of Access]
                  FROM    test.dbo.emplogindetails i  left join test.dbo.emplogindetails o
                  on i.[emp id] = o.[emp id]
                  AND CONVERT(date, i.time) = CONVERT(date, o.time)
                  AND o.time > i.time
                  AND substring ( o.[Area Of Access] ,charindex('in',o.[Area Of Access]),len(o.[Area Of Access]))='in'
                  and substring ( i.[Area Of Access] ,charindex('out',i.[Area Of Access]),len(i.[Area Of Access]))='out'
    
                  and o.Time=(SELECT MIN(o2.time)
                                     FROM test.dbo.emplogindetails   o2
                                     WHERE o2.time > i.time 
                                     and o2.[Emp ID]=i.[Emp ID]
                                     ---and [emp id]='105828' 
                                     )
    --where i.[emp id]='105828' 
    )a where a.status='out')a
    union all
    select CONVERT(VARCHAR(12), (OffFloor +  OnFloor) / 60 / 60 % 24) 
      +':'+ CONVERT(VARCHAR(2), (OffFloor +  OnFloor) / 60 % 60) 
      +':'+ CONVERT(VARCHAR(2), (OffFloor +  OnFloor) % 60) as Calculated_Time 
      ,  CONVERT(VARCHAR(12), (OnFloor) / 60 / 60 % 24)  
      +':'+ CONVERT(VARCHAR(2), (OnFloor) / 60 % 60)+':'+ CONVERT(VARCHAR(2), (OnFloor)  % 60) AS OnFloor
      , case when convert( varchar(10),OffFloor) ='0' then '0:0:0' else OffFloor end OffFloor
    
    
     ,[Emp ID] ,[Area Of Access],
    status,logintime,logouttime
    from (  
    select   '0' as OffFloor, isnull( DATEDIFF(SECOND, a.logintime, a.logouttime) ,0) OnFloor 
    
    ,[Emp ID] ,[Area Of Access],status
    ,logintime,logouttime
     from ( 
     SELECT o.time logouttime,i.Time logintime,i.[Emp ID] 
    ,substring ( i.[Area Of Access] ,charindex('in',i.[Area Of Access]),len(i.[Area Of Access])) status
                  ,i.[Area Of Access]
                  FROM    test.dbo.emplogindetails i  left join test.dbo.emplogindetails o
                  on i.[emp id] = o.[emp id]
                  AND CONVERT(date, i.time) = CONVERT(date, o.time)
                  AND o.time > i.time
                  AND substring ( o.[Area Of Access] ,charindex('out',o.[Area Of Access]),len(o.[Area Of Access]))='out'
                  and substring ( i.[Area Of Access] ,charindex('in',i.[Area Of Access]),len(i.[Area Of Access]))='in'
    
                  and o.Time=(SELECT MIN(o2.time)
                                     FROM test.dbo.emplogindetails   o2
                                     WHERE o2.time > i.time 
                                     and o2.[Emp ID]=i.[Emp ID]
                                    ---and [emp id]='105828'
                                      )
    ---where i.[emp id]='105828' 
    )a where a.status='in')stag)stag
    
    join 
    ----get incount and outcount and tailgate information
    
    (select [emp id]as empid,incount,outcount,
    isnull( incount-outcount ,0) as Tailgate ,Date as ShiftDate
    from ( 
    select  
    i.[Emp ID] ,convert(varchar(10),time,101) as Date,
    count( case  when substring ( i.[Area Of Access] ,charindex('in',i.[Area Of Access]),len(i.[Area Of Access]))='in'
    then   'in' end  )Incount
    ,count( case  when substring ( i.[Area Of Access] ,charindex('out',i.[Area Of Access]),len(i.[Area Of Access]))='out'
    then   'out' end  )outcount
    FROM    test.dbo.emplogindetails i
    --where  [emp id]='105828' 
    group by i.[Emp ID],convert(varchar(10),time,101)
    )cnt)cnt
     on stag.[Emp ID]=cnt.empid and convert(varchar(10),stag.logintime,101)=cnt.ShiftDate
    
     group by EmpID ,Incount ,OutCount, Tailgate
      ,isnull( ShiftDate ,'1900-01-01')
    

    如果退出和登录时间差超过5小时,那么当同一日期有多个班次计算时,此查询不返回预期结果,则视为下一班次。 按照以下给出的逻辑不适用于empid = 5和数据如下所示。 嗨,根据我们的逻辑,一条记录失败。逻辑中需要进行一些更改。以下示例我没有得到预期的输出。

       INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) VALUES (5, N'K4F White Rm IN', CAST(N'2017-08-02T23:30:00.000' AS DateTime))
    GO
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) VALUES (5, N'   K4FWhite Rm OUT', CAST(N'2017-08-03T01:30:00.000' AS DateTime))
    GO
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) VALUES (5, N'K4F White Rm IN', CAST(N'2017-08-03T01:40:00.000' AS DateTime))
    GO
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) VALUES (5, N'K4F White Rm OUT', CAST(N'2017-08-03T04:00:00.000' AS DateTime))
    GO
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) VALUES (5, N'K4F White Rm IN', CAST(N'2017-08-03T04:30:00.000' AS DateTime))
    GO
    INSERT [dbo].[emplogindetails] ([Emp ID], [Area Of Access], [Time]) VALUES (5, N'K4F White Rm OUT', CAST(N'2017-08-03T06:00:00.000' AS DateTime))
    GO
    

    请告诉我如何在SQL Server中完成此任务

1 个答案:

答案 0 :(得分:0)

此查询返回您的预期输出

list2