获得员工工作时间

时间:2014-08-03 03:03:49

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

我有一个名为CHECKTIME的DATETIME列表,表示员工进/出时间。基本上,我有一个查询来执行该功能,但转换不正确。示例如下。

CHECKTIME

2014-04-28 07:58:36.000
2014-04-28 12:00:27.000
2014-04-28 13:00:02.000
2014-04-28 16:57:45.000

当实际结果为Hours = 7.59时,我的查询结果给出了Hour = 7.99。

我想要7.59结果。

SELECT  USERID
       , convert(varchar(10),CHECKTIME,101) as Date
       , SUM(CASE WHEN CHECKTYPE='I' 
                      THEN -1*(datepart(hh,[CHECKTIME])+datepart(mi,[CHECKTIME])/60.0)
                      ELSE datepart(hh,[CHECKTIME])+datepart(mi,[CHECKTIME])/60.0  END) AS Hours

FROM [CHECKINOUT]
WHERE USERID=1003
GROUP BY USERID, CONVERT(varchar(10),[CHECKTIME],101)

3 个答案:

答案 0 :(得分:0)

表达您的查询:

with data(InTime,OutTIme) as (
    select InTime,OutTIme from (values
         (convert(datetime,'2014-04-28 07:58:36.000',120), convert(datetime,'2014-04-28 12:00:27.000',120))
        ,(convert(datetime,'2014-04-28 13:00:02.000',120), convert(datetime,'2014-04-28 16:57:45.000',120))
    )data(InTime,OutTIme)
)
select  cast(dateadd(n,sum(datediff(n,intime,outtime)),0) as time)
from data
go

得出这个:

07:59:00.0000000

我可以自由地手动预先转动数据,以便集中注意如何构建时间转换公式。

更新: - 修改为包含枢轴,生成相同的值:

with data(CheckTime) as (
    select CheckTime from (values
         (convert(datetime,'2014-04-28 07:58:36.000',120))
        ,(convert(datetime,'2014-04-28 12:00:27.000',120))
        ,(convert(datetime,'2014-04-28 13:00:02.000',120))
        ,(convert(datetime,'2014-04-28 16:57:45.000',120))
    )data(CheckTime)
),
pvt as (
    select
        CheckInOut
       ,[0]   as OutTime
       ,[1]   as InTime  
    from (
        select 
             CheckTime
            ,(ROW_NUMBER() over(order by CheckTime)-1) / 2 as CheckInOut
            ,(ROW_NUMBER() over(order by CheckTime)) % 2 as rn
        from data
    )t
    pivot (max(CheckTime) for rn in ([1], [0])) pvt

)
select  cast(dateadd(n,sum(datediff(n,intime,outtime)),0) as time)
from pvt
go

答案 1 :(得分:0)

您提供了示例查询和示例数据。 但样本数据不完整。请添加CHECKTYPE的值,因为这样可以使我们更容易提供解决方案。 同时,它避免了彼得必须做的任何不必要的工作/猜测。 最后,回复就像"它没有工作"等于没有回复,因为它没有给我们带来更进一步的步骤....

答案 2 :(得分:0)

首先,让我们制作一些测试数据:(我冒昧地添加了一个emp id列,这样我就可以添加多个员工时间。

DECLARE @CheckDate TABLE
(
    EmpId INT,
    CheckTime DATETIME
)

INSERT INTO @CheckDate
( EmpId, CheckTime ) 
VALUES
(1, '2014-04-28 07:58:36.000'),
(1, '2014-04-28 12:00:27.000'),
(1, '2014-04-28 13:00:02.000'),
(1, '2014-04-28 16:57:45.000'),
(2, '2014-04-27 1:00:02.000'),
(2, '2014-04-27 16:57:45.000');

现在我们做一个CTE来找到下一行,这样我们就可以获得clockin和clockout的开始和结束。

;WITH CheckRows AS
(
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY EmpId ORDER BY CheckTime) RN
    FROM @CheckDate p
),
CheckBreaks AS
(
    SELECT 
        p.EmpId, 
        p.CheckTime, 
        p.RN, 
        ISNULL(n.CheckTime, 0) NextTime
    FROM CheckRows p
    INNER JOIN CheckRows n
        ON n.RN = p.RN + 1
        AND n.EmpId = p.EmpId
)

现在我们查询数据以查找基于clockins工作的分钟数(RN 1作为第一个clockin / clockout,RN 3作为第二个clockin / clockout,如果你允许更多,只需为每个添加下一对奇数基)

SELECT 
    c.EmpId,
    SUM(CASE WHEN c.RN = 1 OR c.RN = 3 THEN DATEDIFF(MINUTE, c.CheckTime, c.NextTime) ELSE 0 END) DiffTime,
    SUM(CASE WHEN c.RN = 1 OR c.RN = 3 THEN DATEDIFF(MINUTE, c.CheckTime, c.NextTime) ELSE 0 END) / 60 DiffHour,
    SUM(CASE WHEN c.RN = 1 OR c.RN = 3 THEN DATEDIFF(MINUTE, c.CheckTime, c.NextTime) ELSE 0 END) % 60 DiffMinute
FROM CheckBreaks c
GROUP BY c.EmpId

以下是工作小时/分钟的输出:

EmpId   DiffTime    DiffHour    DiffMinute
1   479 7   59
2   957 15  57