找出两个日期之间的时间冲突

时间:2016-06-09 06:18:52

标签: sql sql-server

我正在处理一个应该在两个日期之间找到午餐时间的查询。 例如,午餐时间是下午14:00到下午15:30。 和日期是:'2016-06-09 10:00:00.000'和'2016-06-11 10:00:00.000' 午餐时间在这些日期之间发生两次。 和另一个例子:

'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

但我永远做不到:(

2 个答案:

答案 0 :(得分:4)

这似乎有效:

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

我们使用两个CTE来(a)得出所有相关日期,并且(b)从日期开始计算所有可能的午餐时间,然后最终找到重叠原始时期的所有午餐。

结果:

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

注意 - 许多人过于复杂,试图找出重叠的定义。我在这里使用了一个简单的定义,通常唯一可能需要更改的是决定是使用<还是<=,这取决于你是否考虑邻接的两个句点但不包括重叠的相同时间段。

所以在这里,如果您对上述查询在15:30正好查询 start 期间产生的答案感到不满意,您可能希望更改定义或者结束正好在14:00。

答案 1 :(得分:1)

尝试这个并根据您的要求进行调整:

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