我正在处理一个应该在两个日期之间找到午餐时间的查询。 例如,午餐时间是下午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
但我永远做不到:(
答案 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