Converting Datetime or Time Bucket Values to Numbers
You should probably store the bucket Start
and End
values as int
values, either instead of the times or in addition-to.
To convert datetime
values or expressions into something you can use for matching to the buckets, you can use something like in this code:
DECLARE @when datetime = GETDATE();
SELECT DATEDIFF(minute, DATEADD( day, DATEDIFF(day, 0, @when), 0 ), @when);
--MinutesSinceStartOfDate
-------------------------
--858
--(1 row(s) affected)
If you need seconds, just change the above to something like this:
DECLARE @when datetime = GETDATE();
SELECT DATEDIFF(second, DATEADD( day, DATEDIFF(day, 0, @when), 0 ), @when);
--SecondsSinceStartOfDate
-------------------------
--52466
--(1 row(s) affected)
Matching a Range (Start and End Values) to Buckets (Partitions)
Here's some code that you should be able to adapt to match 'buckets':
CREATE TABLE #buckets (
Id int,
Start int,
Finish int
);
GO
INSERT #buckets ( Id, Start, Finish )
VALUES ( 1, 8, 12 ),
( 2, 12, 13 ),
( 3, 13, 16 ),
( 4, 16, 24 );
DECLARE @beginning int = 9,
@ending int = 17;
SELECT x.*,
EffectiveInterval = x.EffectiveFinish - x.EffectiveStart
FROM ( SELECT *,
EffectiveStart = CASE WHEN Start < @beginning THEN @beginning ELSE Start END,
EffectiveFinish = CASE WHEN Finish > @ending THEN @ending ELSE Finish END
FROM #buckets
WHERE Finish >= @beginning
AND Start <= @ending
) x;
DROP TABLE #buckets;
--(4 row(s) affected)
--Id Start Finish EffectiveStart EffectiveFinish EffectiveInterval
------------- ----------- ----------- -------------- --------------- -----------------
--1 8 12 9 12 3
--2 12 13 12 13 1
--3 13 16 13 16 3
--4 16 24 16 17 1
--(4 row(s) affected)
Comparison of your Code and Mine
CREATE TABLE #buckets (
Id int,
Start time,
Finish time
);
INSERT #buckets ( Id, Start, Finish )
VALUES ( 1, '08:00', '12:00' ),
( 2, '12:00', '12:30' ),
( 3, '12:30', '16:00' ),
( 4, '16:00', '11:59:59.999' );
DECLARE @PunchInDate datetime = '2014-05-15 07:55',
@PunchOutDate datetime = '2014-05-15 17:00';
Select Case When CONVERT(time, @PunchInDate) <= CONVERT(time, Finish)
And CONVERT(time, @PunchInDate) >= CONVERT(time, Start)
AND CONVERT(time, @PunchOutDate) <= CONVERT(time, Finish)
AND CONVERT(time, @PunchOutDate) >= CONVERT(time, Start)Then
'Starts and ends in this range.'
Else
''
End as ScenarioA
, Case
When CONVERT(time, @PunchInDate) <= CONVERT(time, Start)
AND CONVERT(time, @PunchInDate) <= CONVERT(time, Finish)
AND CONVERT(time, @PunchOutDate) >= CONVERT(time, Start)
AND CONVERT(time, @PunchOutDate) <= CONVERT(time, Finish)
Then
'Starts before this range and ends in this range'
Else
''
End as ScenarioB
, Case
When CONVERT(time, @PunchInDate) >= CONVERT(time, Start)
And CONVERT(time, @PunchInDate) <= CONVERT(time, Finish)
And CONVERT(time, @PunchOutDate) >= CONVERT(time, Start)
And CONVERT(time, @PunchOutDate) >= CONVERT(time, Finish)Then
'Starts in this range and ends after the range'
Else ''
END as ScenarioC
, Case
When CONVERT(time, @PunchInDate) <= CONVERT(time, Start)
And CONVERT(time, @PunchInDate) >= CONVERT(time, Finish)
And CONVERT(time, @PunchOutDate) >= CONVERT(time, Start)
And CONVERT(time, @PunchOutDate) >= CONVERT(time, Finish)Then
'Starts before this range and ends after the range'
Else ''
END as ScenarioD
FROM #buckets;
DECLARE @PunchInTime time,
@PunchOutTime time;
SELECT @PunchInTime = CONVERT(time, @PunchInDate),
@PunchOutTime = CONVERT(time, @PunchOutDate);
SELECT x.*,
EffectiveInterval = DATEDIFF(second, x.EffectiveStart, x.EffectiveFinish),
EffectiveIntervalDecimalHourse = DATEDIFF(second, x.EffectiveStart, x.EffectiveFinish) / 3600.
FROM ( SELECT *,
EffectiveStart = CASE WHEN Start < @PunchInTime THEN @PunchInTime ELSE Start END,
EffectiveFinish = CASE WHEN Finish > @PunchOutTime THEN @PunchOutTime ELSE Finish END
FROM #buckets
WHERE Finish >= @PunchInTime
AND Start <= @PunchOutTime
) x;
DROP TABLE #buckets;
--(4 row(s) affected)
--ScenarioA ScenarioB ScenarioC ScenarioD
-------------------------------- ----------------------------------------------- --------------------------------------------- -------------------------------------------------
--(4 row(s) affected)
--Id Start Finish EffectiveStart EffectiveFinish EffectiveInterval EffectiveIntervalDecimalHourse
------------- ---------------- ---------------- ---------------- ---------------- ----------------- ---------------------------------------
--1 08:00:00.0000000 12:00:00.0000000 08:00:00.0000000 12:00:00.0000000 14400 4.000000
--2 12:00:00.0000000 12:30:00.0000000 12:00:00.0000000 12:30:00.0000000 1800 0.500000
--3 12:30:00.0000000 16:00:00.0000000 12:30:00.0000000 16:00:00.0000000 12600 3.500000
--4 16:00:00.0000000 11:59:59.9990000 16:00:00.0000000 11:59:59.9990000 -14401 -4.000277
--(4 row(s) affected)