问题
Looking for a way to group sequential timeclock records into a single row.
The source system has an identity column, employee id, date and in/out flag (1=in & 2=out). Note that the
ID EmployeeID DATE InOut
1019374 5890 2008-08-19 14:07:14 1
1019495 5890 2008-08-19 18:17:08 2
1019504 5890 2008-08-19 18:50:40 1
1019601 5890 2008-08-19 22:06:18 2
I am looking for sql that would give me the following result
EmployeeID ClockIn BreakStart BreakEnd ClockOut
5890 2008-08-19 14:07:14 2008-08-19 18:17:08 2008-08-19 18:50:40 2008-08-19 22:06:18
Note that the ID in the source system is not always sequential because of timeclock edits. Date should be chronological. If only two punches exist, I will need to have the clock in and clock out dates populated with no breaks (or something consistent that I can extract with a case statement). No breaks example below:
EmployeeID ClockIn BreakStart BreakEnd ClockOut
5890 2008-08-19 14:07:14 2008-08-19 22:06:18
Sql version is 2008 R2
Thanks in advance, I can't figure out how to get this to work consistently and your help is greatly appreciated.
回答1:
You can do this with the ROW_NUMBER()
function and a windowed COUNT()
to handle the no break days:
;with cte as (SELECT *,ROW_NUMBER() OVER(PARTITION BY EmployeeID, CAST(dt AS DATE) ORDER BY dt) RN
,COUNT(*) OVER(PARTITION BY EmployeeID, CAST(dt AS DATE)) Dt_CT
FROM Table1)
SELECT EmployeeID
,Dt = CAST(dt AS DATE)
,ClockIn = MAX(CASE WHEN RN = 1 THEN DT END)
,BreakStart = MAX(CASE WHEN Dt_CT = 4 AND RN = 2 THEN DT END)
,BreakEnd = MAX(CASE WHEN Dt_CT = 4 AND RN = 3 THEN DT END)
,ClockOut = MAX(CASE WHEN (Dt_CT = 2 AND RN = 2) OR RN = 4 THEN DT END)
FROM cte
GROUP BY EmployeeID
,CAST(dt AS DATE)
Demo: SQL Fiddle
This is set by day, so a clockout after midnight wouldn't work, and odd number of punches would also be problematic, but for a simple world like your example this will do.
来源:https://stackoverflow.com/questions/25319075/group-sequential-sql-records