I would definitely want to get the shift information into a table to avoid having to update your code if shift patterns change. As I'm sure you've realised, the problem here is that SQL Server has no 'Time' datatype. Try this approach: CREATE TABLE dbo.Shifts ( ShiftID TINYINT IDENTITY(1, 1), ShiftName VARCHAR(30), StartHour TINYINT, StartMinute TINYINT, EndHour TINYINT, EndMinute TINYINT, SpansDayFlag BIT ) INSERT INTO dbo.Shifts ( ShiftName, StartHour, StartMinute, EndHour, EndMinute, SpansDayFlag ) SELECT 'Day Shift', 7 AS ShiftName, 30 AS StartHour, 16 AS StartMinute, 15 AS EndHour, 0 AS EndMinute UNION SELECT 'Night Shift', 19, 30, 4, 30, 1 SELECT cp.* FROM dbo.CP AS cp JOIN dbo.Shifts AS s ON cp.consumed_date BETWEEN DATEADD(minute, s,StartMinute, DATEADD(hour, s.StartHour, DATEADD(day, CASE WHEN s.StartHour > EndHour THEN -1 ELSE 0 END + DATEDIFF(day, 0, cp.consumed_date) - CASE WHEN DATEPART(hour, cp.consumed_date) < 12 THEN CAST(s.SpansDayFlag AS TINYINT) ELSE 0 END, 0 ))) AND DATEADD(minute, s.EndMinute, DATEADD(hour, s.EndHour, DATEADD(day, DATEDIFF(day, 0, cp.consumed_date) + CASE WHEN DATEPART(hour, cp_consumed_date) >=12 THEN CAST(s.SpansDayFlag AS TINYINT) ELSE 0 END, 0 )))
This uses DATEADD in conjunction with DATEDIFF to strip out the time portion of consumed_date before in order to then add the hours and minutes from the shift table to produce start and end datetimes. The SpansDayFlag accommodates those shifts that run over night by subtracting a day from the start of the shift or adding a day to the end of the shift. In order to accommodate this, any dates with an hour part less than 12 are assumed to originate from a shift that started the previous day whilst any from midday onwards are assumed to be part of a shift starting on that day. It could be that this is a problem for you(?) I would also want to put some constraints on the Shifts table to constrain the hour and minute values appropriately, to check that no overlapping ranges exist, etc.