Reputation: 314
I am working on a query that should find lunch times between two dates. for example, lunch time is between 14:00 PM and 15:30 PM. and dates are: '2016-06-09 10:00:00.000' and '2016-06-11 10:00:00.000' lunch time occures two times between these dates. and another examples:
'2016-06-09 15:00:00.000' and '2016-06-11 10:00:00.000' : 2 Times '2016-06-09 17:00:00.000' and '2016-06-11 10:00:00.000' : 1 Time '2016-06-09 13:00:00.000' and '2016-06-11 15:00:00.000' : 3 Times
but I can never do it :(
Upvotes: 2
Views: 330
Reputation: 2970
Try this and make tweeks according to your requirements:
DECLARE @date1 DATETIME = '2016-06-09 08:30:00.000';
DECLARE @date2 DATETIME = '2016-06-13 18:00:00.000';
DECLARE @lunchStart DATETIME = '2016-06-13 14:00:00.000';
DECLARE @lunchEnd DATETIME = '2016-06-13 15:30:00.000';
DECLARE @output INT = 0;
SELECT @output = DATEDIFF(DAY, @date1, @date2)
IF DATEPART(HOUR, @date1) > DATEPART(HOUR, @lunchStart) OR (DATEPART(HOUR, @date1) = DATEPART(HOUR, @lunchStart) AND DATEPART(MINUTE, @date1) <= DATEPART(MINUTE, @lunchStart))
SET @output = @output - 1
IF DATEPART(HOUR, @date2) < DATEPART(HOUR, @lunchEnd) OR (DATEPART(HOUR, @date2) = DATEPART(HOUR, @lunchEnd) AND DATEPART(MINUTE, @date2) = DATEPART(MINUTE, @lunchEnd))
SET @output = @output - 1
PRINT @output
Upvotes: 1
Reputation: 239764
This seems to work:
declare @t table (StartAt datetime not null,EndBefore datetime not null)
insert into @t(StartAt,EndBefore) values
('2016-06-09T15:00:00.000','2016-06-11T10:00:00.000'),
('2016-06-09T17:00:00.000','2016-06-11T10:00:00.000'),
('2016-06-09T13:00:00.000','2016-06-11T15:00:00.000')
;With Dates as (
select MIN(DATEADD(day,DATEDIFF(day,0,StartAt),0)) as ADate
from @t
union all
select DATEADD(day,1,ADate) from Dates
where exists (select * from @t where EndBefore > DATEADD(day,1,ADate))
), Lunches as (
select DATEADD(minute,(14*60),ADate) as StartAt,
DATEADD(minute,(15*60+30),ADate) as EndBefore
from Dates
)
select
*,(select COUNT(*) from Lunches l
where l.StartAt < t.EndBefore and t.StartAt < l.EndBefore)
from @t t
Where we used two CTEs to (a) derive all relevant Dates, and (b) from the dates, compute all possible lunch times, before finally just finding all lunches that overlap the original periods.
Result:
StartAt EndBefore
----------------------- ----------------------- -----------
2016-06-09 15:00:00.000 2016-06-11 10:00:00.000 2
2016-06-09 17:00:00.000 2016-06-11 10:00:00.000 1
2016-06-09 13:00:00.000 2016-06-11 15:00:00.000 3
Note - many people overcomplicate trying to work out a definition of overlaps. I'm using a simple definition here and usually the only thing that might require alteration is deciding on whether to use <
or <=
, which depends on whether you consider two periods that abut but otherwise do not cover the same time periods to be overlapped.
So here, you might want to change the definitions if you're unhappy with the answers the above query produces when you're querying for periods that start at exactly 15:30 or end at exactly 14:00.
Upvotes: 4