需要匹配 ClockIn 和 Clock out,同一天多个时钟 SQL

Need to match ClockIn with Clock out, multiple clocks on same day SQL

我试图让打卡时间和下班时间相互对应,这样我就可以计算在工作时间内 breaks/time 的 worked/amount 工作时间等。我有一个 'Clocking' table 看起来像这样:

模拟数据:

Clock_ID Employee_ID Office Clock_Date Clock_Time ActivityID
1 83 Pretoria CBD 29/03/2022 06:43:00 1
2 55 Pretoria CBD 29/03/2022 06:45:00 1
3 54 Pretoria CBD 29/03/2022 07:00:00 1
4 80 Pretoria CBD 29/03/2022 07:00:00 1
5 75 Pretoria CBD 29/03/2022 07:05:00 1
6 54 Pretoria CBD 29/03/2022 10:59:00 2
7 54 Pretoria CBD 29/03/2022 11:50:00 1
8 55 Pretoria CBD 29/03/2022 12:18:00 2
9 55 Pretoria CBD 29/03/2022 12:30:00 1
10 83 Pretoria CBD 29/03/2022 13:03:00 2
11 80 Pretoria CBD 29/03/2022 13:04:00 2
12 83 Pretoria CBD 29/03/2022 13:39:00 1
13 80 Pretoria CBD 29/03/2022 13:39:00 1
14 75 Pretoria CBD 29/03/2022 15:59:00 2
15 54 Pretoria CBD 29/03/2022 16:00:00 2
16 83 Pretoria CBD 29/03/2022 16:00:00 2
17 80 Pretoria CBD 29/03/2022 16:00:00 2
18 55 Pretoria CBD 29/03/2022 16:00:00 2
19 83 Pretoria CBD 30/03/2022 06:46:00 1
20 55 Pretoria CBD 30/03/2022 06:51:00 1
21 80 Pretoria CBD 30/03/2022 06:54:00 1
22 54 Pretoria CBD 30/03/2022 06:54:00 1
23 54 Pretoria CBD 30/03/2022 11:24:00 2
24 54 Pretoria CBD 30/03/2022 12:11:00 1
25 80 Pretoria CBD 30/03/2022 13:03:00 2
26 80 Pretoria CBD 30/03/2022 14:10:00 1
27 54 Pretoria CBD 30/03/2022 16:01:00 2
28 80 Pretoria CBD 30/03/2022 16:01:00 2
29 83 Pretoria CBD 30/03/2022 16:01:00 2
30 55 Pretoria CBD 30/03/2022 16:05:00 2
31 83 Pretoria CBD 31/03/2022 06:48:00 1
32 55 Pretoria CBD 31/03/2022 06:53:00 1
33 54 Pretoria CBD 31/03/2022 06:55:00 1
34 80 Pretoria CBD 31/03/2022 07:09:00 1
35 54 Pretoria CBD 31/03/2022 12:02:00 2
36 54 Pretoria CBD 31/03/2022 12:09:00 1
37 83 Pretoria CBD 31/03/2022 12:34:00 2
38 80 Pretoria CBD 31/03/2022 12:34:00 2
39 83 Pretoria CBD 31/03/2022 13:09:00 1
40 80 Pretoria CBD 31/03/2022 13:09:00 1
41 55 Pretoria CBD 31/03/2022 13:32:00 2
42 54 Pretoria CBD 31/03/2022 15:56:00 2

ActivityID 决定它是'Clock IN'还是'Clock OUT'

对于任何给定的 Employee_ID,我使用散列 tables 将数据分成 #clockIN 和 #clockOUT tables,如下所示:

#ClockIN

#ClockOUT

我尝试在 table 上的 'Clock_Date' 上使用内部连接来对应 clockIN 和 clockOUT,但是由于员工可以 clockIN 和 OUT,我得到了一个 clockIN 的多个 clockOUT一天多次:见下文:

如您所见,记录匹配不正确,并且是刚加入的日期。

我想不出一种正确加入它们的方法,即 7:30 的 ClockIn 必须与同一天最早的时钟一起加入,并且当天的下一个时钟必须是第二早的 ClockIN,它必须加入第二早的Clock OUT等

我必须使用游标吗?如果是这样,我该如何实施?

我会过去所有SQL我曾经达到这一点。

Drop Table #ClockIn
Drop Table #ClockOut
DROP Table #SortedTimes
DROP Table #WorkBoundries

SELECT Clock_ID, Clock_Date AS Date, Clock_Time
    INTO #ClockIn 
    FROM Clocking
    WHERE Employee_ID = 82 AND ActivityID = 1
    SELECT * FROM #ClockIn

SELECT Clock_ID, Clock_Date AS Date, Clock_Time
    INTO #ClockOut 
    FROM Clocking
    WHERE Employee_ID = 82 AND ActivityID = 2
    SELECT * FROM #ClockOut
            
SELECT #ClockIn.Clock_Time As clockIN, #ClockOut.Clock_Time as ClockOUT, #ClockIn.Date INTO #SortedTimes
FROM #ClockIn
INNER JOIN #ClockOut On #ClockOut.Date = #ClockIN.Date
ORDER BY #ClockIn.Date ASC

SELECT * FROM #SortedTimes

SELECT MIN(clockIn)As TimeIn, MAX(ClockOUT) As TimeOut, [Date] As DayWorked INTO #WorkBoundries
FROM #SortedTimes
GROUP BY [Date]
SELECT * FROM #WorkBoundries

#WorkBoundries 只是为了查看此人是否在工作时间内打卡 IN/OUT。

提前感谢您的帮助

也许这可以帮到你

select e.empid,
       e.clockdate,
       e.clocktime as starttime,
       o.clocktime as endtime
from   emp e
  outer apply (select top 1 e2.clocktime 
               from   emp e2 
               where  e2.empid = e.empid
               and    e2.activity = 2
               and    e2.clockdate = e.clockdate
               and    e2.clocktime > e.clocktime
               order by e2.clocktime
              ) o
where  e.activity = 1
order by e.empid, e.clocktime

DBFiddle这里

结果是这样

empid clockdate starttime endtime
55 2022-03-29 06:45:00.0000000 12:18:00.0000000
55 2022-03-29 12:30:00.0000000 null
83 2022-03-29 06:43:00.0000000 13:03:00.0000000
83 2022-03-29 13:39:00.0000000 16:00:00.0000000

您可以在 基础 table 的单次扫描 中执行此操作,无需连接,方法是使用 window 函数:

WITH NextValues AS (
    SELECT *,
      NextClockOut = LEAD(CASE WHEN c.ActivityID = 2 THEN c.Clock_Time END)
        OVER (PARTITION BY c.Office, c.Employee_ID, c.Clock_Date
             ORDER BY c.Clock_Time)
    FROM Clocking c
)
SELECT
  nv.Employee_ID,
  nv.Office,
  nv.Clock_Date,
  ClockIn = nv.Clock_Time,
  ClockOut = nv.NextClockOut
FROM NextValues nv
WHERE nv.ActivityID = 1;

db<>fiddle