4

我有一张供员工打卡/打卡的考勤表,布局如下:

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. 我如何处理没有打卡的记录?我可以设置类似 if null,时间等于下一个日期03:59:59吗?

提前致谢。

我用 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
4

2 回答 2

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
于 2013-09-25T20:16:05.610 回答
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”怎么办?
  • 如果连续有两个“进”或两个“出”怎么办?

但是,处理没有时钟输出的情况。因为分区的最后一行的 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'

它更复杂,效率更低,但在面对无效的“输入”和“输出”序列时更健壮。再说一次,它处理无效序列的方式可能是也可能不是您真正想要的行为。

于 2013-09-25T21:30:31.740 回答