需要匹配 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;
我试图让打卡时间和下班时间相互对应,这样我就可以计算在工作时间内 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;