Tsql Complex Query : Calculating Total timetaken for an event in set of events when we have starttime and endtime
Hi... I am trying to take data from a inspection/timeclock software and create useable reports for our payroll department.
My problem is that the data is in a difficult form to sum and I am not entirely sure how I can do this.
The employees perform inspections on their vehicle with a handheld unit. For each row of data there is a starttime and an endtime which shows the beginning and ending times just for the inspection itself. An inspection might take anywhere from 30 seconds to 15 minutes.
Before an employee starts a route, they must perform an inspection. They will choose a category at the beginning of the inspection that will specify what type of route they are about to run (there could be any number of different route types). They then perform the inspection (this is their IN time punch) and cradle the handheld unit, which will send the data up to the system. The employee then begins his/her route.
When the employee is finsihed with his/her route, they are required to run another inspection, which will signify their OUT time punch.
An employee could run a number of routes during the day. If the employee performs the inspections like they should, there should be two punches for each route they run.
My issue is that I have to group and sort these pairs of time punches and sum the total time for each category and person.
I have no idea how I can do this because each punch is in its own row of data and I have to use the "starttime" from the first punch for a route and the "endtime" for the second punch for the route as the beginning and end punches for the employee for that particular route type. Then I have to figure out the difference in minutes between those two punches and display that on my report.
The data would look like this:
From that data you can see that the driver was Tory Bradley. She ran a REGULAR route type first and the beginning inspection for that started at 12 noon. She finished the inspection at 12:01pm, so the inspection took 1 minute and 23 seconds to complete.
She then ran her route. She finished the route and ran an inspection at 13:37 and that inspection was finished within 48 seconds.
To find her total hours, I would need to take the "cstarttime" from the first inspection for the REGULAR type as her IN punch and the "cendtime" from her second inspection for the REGULAR type as her OUT punch.
Likewise, you can see that she ran another route with a type of MID DAY after the first route and you can see her punches for that route. Then she ran a FIELD TRIP route and then two REGULAR routes.
Ideally, I would be able to produce a report that shows something like this:
Driver: Tory Bradley
-- Route Type -- Duration (# minutes)
REGULAR -- 149 minutes
MIDDAY -- 12 minutes
FIELDTRIP -- 7 minutes
------- Tory Bradley Total: 168 minutes
Solution :
Here is the correct query that calculates the output given your latest set of sample data:
My problem is that the data is in a difficult form to sum and I am not entirely sure how I can do this.
The employees perform inspections on their vehicle with a handheld unit. For each row of data there is a starttime and an endtime which shows the beginning and ending times just for the inspection itself. An inspection might take anywhere from 30 seconds to 15 minutes.
Before an employee starts a route, they must perform an inspection. They will choose a category at the beginning of the inspection that will specify what type of route they are about to run (there could be any number of different route types). They then perform the inspection (this is their IN time punch) and cradle the handheld unit, which will send the data up to the system. The employee then begins his/her route.
When the employee is finsihed with his/her route, they are required to run another inspection, which will signify their OUT time punch.
An employee could run a number of routes during the day. If the employee performs the inspections like they should, there should be two punches for each route they run.
My issue is that I have to group and sort these pairs of time punches and sum the total time for each category and person.
I have no idea how I can do this because each punch is in its own row of data and I have to use the "starttime" from the first punch for a route and the "endtime" for the second punch for the route as the beginning and end punches for the employee for that particular route type. Then I have to figure out the difference in minutes between those two punches and display that on my report.
The data would look like this:
id | operator | routetype | RouteTypeCategory | ctimestamp | cstarttime | cendtime | NumMins |
8247 | Driver, Tory Bradley | 0 | Regular | 11/27/09 12:00 | 11/27/09 12:00 | 11/27/09 12:01 | 1.23 |
8248 | Driver, Tory Bradley | 0 | Regular | 11/27/09 13:37 | 11/27/09 13:37 | 11/27/09 13:37 | 0.48 |
8249 | Driver, Tory Bradley | 5 | Mid Day | 11/27/09 13:38 | 11/27/09 13:38 | 11/27/09 13:38 | 0.38 |
8250 | Driver, Tory Bradley | 5 | Mid Day | 11/27/09 13:50 | 11/27/09 13:49 | 11/27/09 13:50 | 0.47 |
8251 | Driver, Tory Bradley | 45 | Field Trip | 11/27/09 13:51 | 11/27/09 13:51 | 11/27/09 13:51 | 0.48 |
8252 | Driver, Tory Bradley | 45 | Field Trip | 11/27/09 13:58 | 11/27/09 13:58 | 11/27/09 13:58 | 0.4 |
8253 | Driver, Tory Bradley | 0 | Regular | 11/27/09 13:59 | 11/27/09 13:59 | 11/27/09 14:01 | 1.65 |
8254 | Driver, Tory Bradley | 0 | Regular | 11/27/09 14:37 | 11/27/09 14:36 | 11/27/09 14:37 | 0.62 |
8255 | Driver, Tory Bradley | 0 | Regular | 11/27/09 14:57 | 11/27/09 14:57 | 11/27/09 14:58 | 0.72 |
8256 | Driver, Tory Bradley | 0 | Regular | 11/27/09 15:02 | 11/27/09 15:02 | 11/27/09 15:03 | 0.68 |
From that data you can see that the driver was Tory Bradley. She ran a REGULAR route type first and the beginning inspection for that started at 12 noon. She finished the inspection at 12:01pm, so the inspection took 1 minute and 23 seconds to complete.
She then ran her route. She finished the route and ran an inspection at 13:37 and that inspection was finished within 48 seconds.
To find her total hours, I would need to take the "cstarttime" from the first inspection for the REGULAR type as her IN punch and the "cendtime" from her second inspection for the REGULAR type as her OUT punch.
Likewise, you can see that she ran another route with a type of MID DAY after the first route and you can see her punches for that route. Then she ran a FIELD TRIP route and then two REGULAR routes.
Ideally, I would be able to produce a report that shows something like this:
Driver: Tory Bradley
-- Route Type -- Duration (# minutes)
REGULAR -- 149 minutes
MIDDAY -- 12 minutes
FIELDTRIP -- 7 minutes
------- Tory Bradley Total: 168 minutes
Solution :
Here is the correct query that calculates the output given your latest set of sample data:
DECLARE @ZonarInspections TABLE
(
id INT,
operator VARCHAR(30),
opid INT,
routetype INT,
ctimestamp DATETIME,
cstarttime DATETIME,
cendtime DATETIME,
NumMins NUMERIC(18,8)
)
DECLARE @ZonarInspectionsData TABLE
(
RouteType INT,
RouteTypeCat VARCHAR(20)
)
INSERT INTO @ZonarInspectionsData
SELECT 0, 'Regular' UNION ALL
SELECT 1, 'Route Type 1' UNION ALL
SELECT 5, 'Mid' UNION ALL
SELECT 43, 'Route Type 43' UNION ALL
SELECT 45, 'Field Trip' UNION ALL
SELECT 63, 'Route Type 63'
INSERT INTO @ZonarInspections
SELECT 8235, 'Manager, Michael Waters', 60, 0, '11/25/09 8:18', '11/25/09 8:18', '11/25/09 8:19', 1.63 UNION ALL
SELECT 8236, 'Manager, Michael Waters', 60, 0, '11/25/09 8:41', '11/25/09 8:41', '11/25/09 8:41', 0.45 UNION ALL
SELECT 8237, 'Manager, Michael Waters', 60, 1, '11/25/09 8:52', '11/25/09 8:52', '11/25/09 8:53', 0.42 UNION ALL
SELECT 8238, 'Manager, Michael Waters', 60, 1, '11/25/09 9:13', '11/25/09 9:13', '11/25/09 9:14', 0.47 UNION ALL
SELECT 8239, 'Manager, Michael Waters', 60, 43, '11/25/09 9:33', '11/25/09 9:33', '11/25/09 9:34', 0.68 UNION ALL
SELECT 8240, 'Manager, Michael Waters', 60, 43, '11/25/09 9:40', '11/25/09 9:40', '11/25/09 9:41', 0.58 UNION ALL
SELECT 8241, 'Manager, Michael Waters', 60, 45, '11/25/09 9:42', '11/25/09 9:41', '11/25/09 9:42', 0.5 UNION ALL
SELECT 8242, 'Manager, Michael Waters', 60, 45, '11/25/09 10:13', '11/25/09 10:12', '11/25/09 10:13', 0.5 UNION ALL
SELECT 8243, 'Manager, Michael Waters', 60, 63, '11/25/09 12:14', '11/25/09 12:13', '11/25/09 12:14', 0.68 UNION ALL
SELECT 8244, 'Manager, Michael Waters', 60, 63, '11/25/09 13:10', '11/25/09 13:10', '11/25/09 13:11', 0.58 UNION ALL
SELECT 8245, 'Manager, Michael Waters', 60, 0, '11/25/09 15:09', '11/25/09 15:09', '11/25/09 15:09', 0.37 UNION ALL
SELECT 8247, 'Driver, Tory Bradley', 55, 0, '11/27/09 12:00', '11/27/09 12:00', '11/27/09 12:01', 1.23 UNION ALL
SELECT 8248, 'Driver, Tory Bradley', 55, 0, '11/27/09 13:37', '11/27/09 13:37', '11/27/09 13:37', 0.48 UNION ALL
SELECT 8249, 'Driver, Tory Bradley', 55, 5, '11/27/09 13:38', '11/27/09 13:38', '11/27/09 13:38', 0.38 UNION ALL
SELECT 8250, 'Driver, Tory Bradley', 55, 5, '11/27/09 13:50', '11/27/09 13:49', '11/27/09 13:50', 0.47 UNION ALL
SELECT 8251, 'Driver, Tory Bradley', 55, 45, '11/27/09 13:51', '11/27/09 13:51', '11/27/09 13:51', 0.48 UNION ALL
SELECT 8252, 'Driver, Tory Bradley', 55, 45, '11/27/09 13:58', '11/27/09 13:58', '11/27/09 13:58', 0.4 UNION ALL
SELECT 8253, 'Driver, Tory Bradley', 55, 0, '11/27/09 13:59', '11/27/09 13:59', '11/27/09 14:01', 1.65 UNION ALL
SELECT 8254, 'Driver, Tory Bradley', 55, 0, '11/27/09 14:37', '11/27/09 14:36', '11/27/09 14:37', 0.62 UNION ALL
SELECT 8255, 'Driver, Tory Bradley', 55, 0, '11/27/09 14:57', '11/27/09 14:57', '11/27/09 14:58', 0.72 UNION ALL
SELECT 8256, 'Driver, Tory Bradley', 55, 0, '11/27/09 15:02', '11/27/09 15:02', '11/27/09 15:03', 0.68
;WITH typeCTE AS
(
SELECT *
, time_punch_type = 2 - (ROW_NUMBER() OVER (PARTITION BY zi.opid, zi.RouteType ORDER BY zi.ctimestamp) % 2)
FROM @ZonarInspections zi
)
SELECT zi_start.opid
, zi_start.operator
, zi_start.RouteType
, zid.RouteTypeCat
, total_nummins = SUM(zi_start.nummins) + SUM(zi_end.nummins)
, total_duration_minutes = SUM(DATEDIFF(minute, zi_start.cstarttime, zi_end.cendtime))
FROM typeCTE zi_start
JOIN @ZonarInspectionsData zid
ON zi_start.RouteType = zid.RouteType
LEFT JOIN typeCTE zi_end
ON zi_start.opid = zi_end.opid
AND zi_start.RouteType = zi_end.RouteType
AND zi_start.cendtime = (
SELECT MAX(x.cendtime)
FROM typeCTE x
WHERE x.cendtime < zi_end.cstarttime
AND x.opid = zi_end.opid
AND x.RouteType = zi_end.RouteType
AND x.time_punch_type = 1
)
AND zi_end.time_punch_type = 2
WHERE zi_start.time_punch_type = 1
GROUP BY zi_start.opid
, zi_start.operator
, zi_start.RouteType
, zid.RouteTypeCat
ORDER BY zi_start.opid, zi_start.RouteType
This is the output generated:opid | operator | RouteType | RouteTypeCat | total_nummins | total_duration_minutes |
55 | Driver, Tory Bradley | 0 | Regular | 5.38 | 141 |
55 | Driver, Tory Bradley | 5 | Mid | 0.85 | 12 |
55 | Driver, Tory Bradley | 45 | Field Trip | 0.88 | 7 |
60 | Manager, Michael Waters | 0 | Regular | 2.45 | 23 |
60 | Manager, Michael Waters | 1 | Route Type 1 | 0.89 | 22 |
60 | Manager, Michael Waters | 43 | Route Type 43 | 1.26 | 8 |
60 | Manager, Michael Waters | 45 | Field Trip | 1 | 32 |
60 | Manager, Michael Waters | 63 | Route Type 63 | 1.26 | 58 |
Comments
Post a Comment