add batch remove batch split batch comment selection show hidden batches hide batch highlight batch
db<>fiddle
donate feedback about
By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
-- Create the Tasks table
CREATE TABLE Tasks (
TaskID INT PRIMARY KEY,
Technician NVARCHAR(50),
StartDate DATETIME,
EndDate DATETIME
);
-- Insert sample data into the Tasks table
INSERT INTO Tasks (TaskID, Technician, StartDate, EndDate)
VALUES
(1, 'Tech1', '2023-10-30 08:05:00', '2023-10-30 08:25:00'),
(2, 'Tech1', '2023-10-30 08:20:00', '2023-10-30 08:35:00'),
(3, 'Tech2', '2023-10-30 08:30:00', '2023-10-30 09:10:00'),
(4, 'Tech1', '2023-10-30 09:05:00', '2023-10-30 09:45:00'),
(5, 'Tech3', '2023-10-30 08:10:00', '2023-10-30 08:20:00'),
(6, 'Tech3', '2023-10-30 08:30:00', '2023-10-30 08:45:00');
6 rows affected
-- Generate a Time Blocks table containing every 15 minutes since 2000-01-01.
-- If you have a numbers table going from 0 to 1million or so, use that and multiply each number by 15.
-- FifteenMinuteBlocks uses generate_series() to create that numbers table on the fly for us.
-- But generate_series() is only available starting with SQL Server 2022.
WITH FifteenMinuteBlocks AS
(
SELECT value * 15 AS Fifteens
FROM generate_series(0, 1000000) t
)
SELECT DATEADD(minute, b.Fifteens, '2000-01-01') AS TimeBlockStart
, DATEADD(minute, b.Fifteens + 15, '2000-01-01') AS TimeBlockEnd
INTO #TimeBlocks
FROM FifteenMinuteBlocks b
;
1000001 rows affected
SELECT TOP 10 *
FROM #TimeBlocks;
TimeBlockStart TimeBlockEnd
2000-01-01 00:00:00.000 2000-01-01 00:15:00.000
2000-01-01 00:15:00.000 2000-01-01 00:30:00.000
2000-01-01 00:30:00.000 2000-01-01 00:45:00.000
2000-01-01 00:45:00.000 2000-01-01 01:00:00.000
2000-01-01 01:00:00.000 2000-01-01 01:15:00.000
2000-01-01 01:15:00.000 2000-01-01 01:30:00.000
2000-01-01 01:30:00.000 2000-01-01 01:45:00.000
2000-01-01 01:45:00.000 2000-01-01 02:00:00.000
2000-01-01 02:00:00.000 2000-01-01 02:15:00.000
2000-01-01 02:15:00.000 2000-01-01 02:30:00.000
-- Basically, we're just joining the TimeBlocks table to our data.
SELECT t.*
, tb.*
FROM Tasks t
INNER JOIN #TimeBlocks tb
ON ( t.StartDate < tb.TimeBlockEnd
AND t.EndDate > tb.TimeBlockStart
);
TaskID Technician StartDate EndDate TimeBlockStart TimeBlockEnd
1 Tech1 2023-10-30 08:05:00.000 2023-10-30 08:25:00.000 2023-10-30 08:00:00.000 2023-10-30 08:15:00.000
1 Tech1 2023-10-30 08:05:00.000 2023-10-30 08:25:00.000 2023-10-30 08:15:00.000 2023-10-30 08:30:00.000
2 Tech1 2023-10-30 08:20:00.000 2023-10-30 08:35:00.000 2023-10-30 08:15:00.000 2023-10-30 08:30:00.000
2 Tech1 2023-10-30 08:20:00.000 2023-10-30 08:35:00.000 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000
3 Tech2 2023-10-30 08:30:00.000 2023-10-30 09:10:00.000 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000
3 Tech2 2023-10-30 08:30:00.000 2023-10-30 09:10:00.000 2023-10-30 08:45:00.000 2023-10-30 09:00:00.000
3 Tech2 2023-10-30 08:30:00.000 2023-10-30 09:10:00.000 2023-10-30 09:00:00.000 2023-10-30 09:15:00.000
4 Tech1 2023-10-30 09:05:00.000 2023-10-30 09:45:00.000 2023-10-30 09:00:00.000 2023-10-30 09:15:00.000
4 Tech1 2023-10-30 09:05:00.000 2023-10-30 09:45:00.000 2023-10-30 09:15:00.000 2023-10-30 09:30:00.000
4 Tech1 2023-10-30 09:05:00.000 2023-10-30 09:45:00.000 2023-10-30 09:30:00.000 2023-10-30 09:45:00.000
5 Tech3 2023-10-30 08:10:00.000 2023-10-30 08:20:00.000 2023-10-30 08:00:00.000 2023-10-30 08:15:00.000
5 Tech3 2023-10-30 08:10:00.000 2023-10-30 08:20:00.000 2023-10-30 08:15:00.000 2023-10-30 08:30:00.000
6 Tech3 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000
-- And then we need to calculate the number of minutes that are within our time block.
SELECT t.TaskID
, t.Technician
, DATEDIFF(minute
, IIF(t.StartDate < tb.TimeBlockStart, tb.TimeBlockStart, t.StartDate)
, IIF(t.EndDate > tb.TimeBlockEnd, tb.TimeBlockEnd, t.EndDate)
) AS Minutes
, t.StartDate
, t.EndDate
, tb.TimeBlockStart
, tb.TimeBlockEnd
FROM Tasks t
INNER JOIN #TimeBlocks tb
ON ( t.StartDate < tb.TimeBlockEnd
AND t.EndDate > tb.TimeBlockStart
);
TaskID Technician Minutes StartDate EndDate TimeBlockStart TimeBlockEnd
1 Tech1 10 2023-10-30 08:05:00.000 2023-10-30 08:25:00.000 2023-10-30 08:00:00.000 2023-10-30 08:15:00.000
1 Tech1 10 2023-10-30 08:05:00.000 2023-10-30 08:25:00.000 2023-10-30 08:15:00.000 2023-10-30 08:30:00.000
2 Tech1 10 2023-10-30 08:20:00.000 2023-10-30 08:35:00.000 2023-10-30 08:15:00.000 2023-10-30 08:30:00.000
2 Tech1 5 2023-10-30 08:20:00.000 2023-10-30 08:35:00.000 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000
3 Tech2 15 2023-10-30 08:30:00.000 2023-10-30 09:10:00.000 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000
3 Tech2 15 2023-10-30 08:30:00.000 2023-10-30 09:10:00.000 2023-10-30 08:45:00.000 2023-10-30 09:00:00.000
3 Tech2 10 2023-10-30 08:30:00.000 2023-10-30 09:10:00.000 2023-10-30 09:00:00.000 2023-10-30 09:15:00.000
4 Tech1 10 2023-10-30 09:05:00.000 2023-10-30 09:45:00.000 2023-10-30 09:00:00.000 2023-10-30 09:15:00.000
4 Tech1 15 2023-10-30 09:05:00.000 2023-10-30 09:45:00.000 2023-10-30 09:15:00.000 2023-10-30 09:30:00.000
4 Tech1 15 2023-10-30 09:05:00.000 2023-10-30 09:45:00.000 2023-10-30 09:30:00.000 2023-10-30 09:45:00.000
5 Tech3 5 2023-10-30 08:10:00.000 2023-10-30 08:20:00.000 2023-10-30 08:00:00.000 2023-10-30 08:15:00.000
5 Tech3 5 2023-10-30 08:10:00.000 2023-10-30 08:20:00.000 2023-10-30 08:15:00.000 2023-10-30 08:30:00.000
6 Tech3 15 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000 2023-10-30 08:30:00.000 2023-10-30 08:45:00.000
-- Then we SUM the minutes for each tech within the time block.
SELECT
t.Technician
, tb.TimeBlockStart
, SUM(DATEDIFF(minute
, IIF(t.StartDate < tb.TimeBlockStart, tb.TimeBlockStart, t.StartDate)
, IIF(t.EndDate > tb.TimeBlockEnd, tb.TimeBlockEnd, t.EndDate)
)) AS Minutes
FROM Tasks t
INNER JOIN #TimeBlocks tb
ON ( t.StartDate < tb.TimeBlockEnd
AND t.EndDate > tb.TimeBlockStart
)
GROUP BY t.Technician
, tb.TimeBlockStart
ORDER BY t.Technician
, tb.TimeBlockStart
;
Technician TimeBlockStart Minutes
Tech1 2023-10-30 08:00:00.000 10
Tech1 2023-10-30 08:15:00.000 20
Tech1 2023-10-30 08:30:00.000 5
Tech1 2023-10-30 09:00:00.000 10
Tech1 2023-10-30 09:15:00.000 15
Tech1 2023-10-30 09:30:00.000 15
Tech2 2023-10-30 08:30:00.000 15
Tech2 2023-10-30 08:45:00.000 15
Tech2 2023-10-30 09:00:00.000 10
Tech3 2023-10-30 08:00:00.000 5
Tech3 2023-10-30 08:15:00.000 5
Tech3 2023-10-30 08:30:00.000 15