查询时间卡数据库

时间:2013-09-25 17:07:50

标签: tsql

我有一张时间卡表供员工上班/下班,布局如下:

employeeID  Clock-in DateTime   Clock Type
1004        24/09/2013 13:08    in
1004        25/09/2013 00:50    out
1005        24/09/2013 12:08    in
1005        25/09/2013 03:55    out
2003        24/09/2013 10:06    in
2003        24/09/2013 15:42    out
2003        24/09/2013 17:33    in
2003        24/09/2013 22:17    out

我怎样才能让它像:

Date        employeeID  Clock-in            Clock-out           time worked (in hours to 2 decimal place)
24/09/2013  1004        24/09/2013 13:08    25/09/2013 00:50    xx.xx
24/09/2013  1005        24/09/2013 12:08    25/09/2013 03:55    xx.xx
24/09/2013  2003        24/09/2013 10:06    24/09/2013 15:42    xx.xx
24/09/2013  2003        24/09/2013 17:33    24/09/2013 22:17    xx.xx

请注意:

  1. 员工可以有多个时钟输入/输出(即上午/下午,夜班)
  2. 日期从04:00:0003:59:59(即上例中,全部归类为24/09/2013
  3. 如何处理没有时钟输出的记录?我可以设置如果null,时间等于下一个日期03:59:59吗?
  4. 提前致谢。

    我用以下内容更新了jods建议:

    3组进/出记录的示例

    EmployeeID  CardDate            PunchType
    1000        21/09/2013 07:43    in
    1000        21/09/2013 11:29    out
    1000        21/09/2013 12:39    in
    1000        21/09/2013 20:37    out
    1000        21/09/2013 21:58    in
    1000        22/09/2013 00:16    out
    

    您的查询返回

    Date        EmployeeID  clockInTime clockOutTime
    21/09/2013  1000        07:43:57    00:16:22
    21/09/2013  1000        21:58:40    11:29:22
    

2 个答案:

答案 0 :(得分:0)

如果您使用SQL SERVER 2005及更高版本。你可以试试这个

WITH cte AS (
SELECT
   [employeeID]
    ,ti.ClockIn
    ,ClockOut = (SELECT MIN(t.ClockIn) 
                 FROM timecard t 
                 WHERE ti.employeeID = t.employeeID 
                 AND t.Type = 'out' 
                 AND t.ClockIn > ti.ClockIn
                 AND t.ClockIn < DATEADD(hour, 24 + 4 , CAST(CAST(ti.ClockIn AS DATE) AS datetime))
                )  
    ,NextDayLimit = DATEADD(SECOND, -1, DATEADD(hour, 24 + 4 , CAST(CAST(ti.ClockIn AS DATE) AS datetime)))
FROM timecard ti
WHERE Type = 'in'
)
SELECT 
    employeeID,
    ClockIn,
    ISNULL(ClockOut, NextDayLimit) AS ClockOut,
    CAST(DATEDIFF(minute, ClockIn, ISNULL(ClockOut, NextDayLimit))/60.0 AS NUMERIC(19,2)) AS TimeWorked
from cte
ORDER BY    employeeID, ClockIn

答案 1 :(得分:0)

如果您使用SQL 2012,这是使用LEAD的基本思路:

SELECT 
   ROUND(clockIn) as [date],
   employeeId,
   clockIn as clockInTime,
   LEAD(clockIn) OVER (PARTITION BY employeeId, ROUND(clockIn) ORDER BY clockIn) as clockOutTime
FROM TimeCard
WHERE clockType = 'in'

然后你可以通过计算时钟输入和时钟输出时间来获得时间。

有很多角落案件,并非全部处理:

  • 工作期间是否可以跨越午夜?
  • 如果第一个时钟输入是'out'类型怎么办?
  • 如果连续两个'in'或'out'会怎么样?

但是没有时钟输出的情况是处理。由于分区的最后一行的LEAD值为NULL。

这是一个更健壮的选项,适用于SQL 2005:

WITH NumberedClockIn AS (
  SELECT 
    ROUND(clockIn) as [date],
    employeeId,
    clockIn as clockTime,
    clockType,
    ROW_NUMBER() OVER (PARTITION BY employeeId, ROUND(clockIn) ORDER BY clockIn) as rn
  FROM TimeCard
)
SELECT 
  IN.[date], 
  IN.employeeId, 
  IN.clockTime as clockInTime,
  OUT.clockTime as clockOutTime
FROM NumberedClockIn IN
LEFT OUTER JOIN NumberedClockIn OUT
  ON IN.[date] = OUT.[date]
 AND IN.employeeId = OUT.employeeID
 AND IN.rn + 1 = OUT.rn
WHERE IN.clockType = 'in'
  AND OUT.clockType = 'out'

它更复杂,效率更低,但在无效的“输入”和“输出”序列中更加强大。然后,它处理无效序列的方式可能是也可能不是你真正想要的行为。