计算员工时间表数据

时间:2018-05-21 19:18:59

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

假设您有一个时钟表,每个时钟事件只有一个时间戳条目:

Userid  CheckTime
312     2018-05-08 05:52:00
312     2018-05-08 18:06:00
312     2018-05-10 05:55:00
312     2018-05-10 18:00:00
312     2018-05-11 05:58:00
312     2018-05-11 18:00:00
312     2018-05-12 05:35:00
312     2018-05-12 18:00:00

我如何计算SQL Server中的事件以显示这样的内容?

Day       Date       In      Out        Reg      OT
Tuesday   5/8/2018   5:52AM  6:06PM     12.00    0.00
Thursday  5/10/2018  5:55AM  6:00PM     12.00    0.00
Friday    5/11/2018  5:58AM  6:00PM     12.00    0.00
Saturday  5/12/2018  5:35AM  6:00PM     12.00    0.42

另外,我们有隔夜的人在一天内开始轮班并继续工作到另一天。

我不确定如何计算这个,因为它是基于行和基于列的。

我已经尝试过了......但它没有正常工作......

         ;WITH emp
                 AS (SELECT [UserID],
                            [CheckTime],
                    CAST([CheckTime] AS DATE) AS [Day],
                    Row_Number()
                    OVER( PARTITION BY [UserID], CAST([CheckTime] AS DATE)
                     ORDER BY [UserID], [CheckTime]) AS [RowNumber]
                     FROM   [dbo].[Clock_Data] WHERE CHECKTIME 
                     BETWEEN '2018-05-06' AND '2018-05-13')
            SELECT 
             t1.[UserID], 
             E.[Last Name]AS [EMPID],
                   MIN(t1.[CheckTime]) AS [time_in],
                   MAX(t2.[CheckTime]) AS [time_out],
                   CAST((SUM(ISNULL(DATEDIFF(ss,  t1.[CheckTime], 
            t2.[CheckTime]) , 0)) / 3600)-1 AS VARCHAR(10)) + '.' +
            FROM   emp AS t1
                   LEFT JOIN emp AS t2
                          ON ( t1.[UserID] = t2.[UserID]
                               AND t1.[Day] = t2.[Day]
                               AND t1.[RowNumber] = ( t2.[RowNumber] - 1 )
                               AND t2.[RowNumber] % 2 = 0 
                               )
                    INNER JOIN Employees as E on t1.Userid = E.[ID Number]
            GROUP  BY t1.[UserID], E.[Last Name]
            ORDER  BY t1.[UserID]

1 个答案:

答案 0 :(得分:2)

正如上面的评论中所提到的,这种类型的查询存在很多复杂性。错过/重复拳。夏令时。假期,周末。对于您需要的任何规则,可能算作O / T的事物类型。但是对于一个很好的干净数据集,你可以相当容易地做到这一点。这绝不是一个完整的解决方案,因为您有很多东西需要详细说明。但这应该是一个不错的起点。

declare @Something table
(
    Userid int
    , CheckTime datetime
)

insert @Something values
    (312, '2018-05-08 05:52:00')
    , (312, '2018-05-08 18:06:00')
    , (312, '2018-05-10 05:55:00')
    , (312, '2018-05-10 18:00:00')
    , (312, '2018-05-11 05:58:00')
    , (312, '2018-05-11 18:00:00')
    , (312, '2018-05-12 05:35:00')
    , (312, '2018-05-12 18:00:00');

with OrderedResults as
(
    select *
        , RowNum = ROW_NUMBER() over(partition by Userid order by CheckTime)
    from @Something
)
, InPunch as
(
    select *
        , GroupNum = Row_Number () over(partition by Userid order by RowNum)
    from OrderedResults
    where RowNum % 2 = 1
)
, OutPunch as 
(
    select *
        , GroupNum = Row_Number () over(partition by Userid order by RowNum)
    from OrderedResults
    where RowNum % 2 = 0
)

select ip.Userid
    , PunchDate = convert(date, ip.CheckTime)
    , CheckIn = ip.CheckTime
    , CheckOut = op.CheckTime
from InPunch ip
join OutPunch op on op.GroupNum = ip.GroupNum