找到重叠的时间范围

时间:2011-09-28 13:57:10

标签: tsql

我很惊讶这还没有出现。

在T-SQL中,我需要找到与每日间隔重叠的间隔(由startDateTime和endDateTime定义)(例如,上午9点至下午5点)。

例如,使用表格:

CREATE TABLE [dbo].[Interval](
    [startDateTime] [datetime] NOT NULL,
    [endDateTime] [datetime] NOT NULL
)

解决方案是只返回重叠间隔的过程:

CREATE PROCEDURE FindIntervals
    -- Add the parameters for the stored procedure here
    @from varchar(5) = '9:00', 
    @to varchar(5) = '17:00'
AS
BEGIN
    select * from Interval
    where ...
END
GO

编辑: 示例区间:

  1. 2011年9月7日上午8:00 - 2011年9月7日晚上8:30
  2. 2011年9月7日上午11:00 - 2011年9月7日下午1:00
  3. 2011年9月7日下午1:00 - 2011年9月7日下午6:00
  4. 2011年9月9日上午8:00 - 2011年9月9日晚上8:30
  5. 2011年9月9日上午11:00 - 2011年9月9日下午1:00
  6. 2011年9月9日下午1:00 - 2011年9月9日下午6:00
  7. 因此,对于给定的间隔“九到五”,应该返回2,3,5和6,因为它们与给定的输入重叠。

    但是,

    1. 2011年9月9日上午8:00 - 2011年9月10日晚上8:30
    2. 也适合,因为它包括整天。

      请帮助我在T-SQL中匹配字符串和日期时间值,而不是抽象的“少于”/“大于”的解决方案。

1 个答案:

答案 0 :(得分:4)

declare @Interval table
(
  startDateTime datetime,
  endDateTime datetime
)

insert into @Interval values
('2011-09-07T08:00:00', '2011-09-07T08:30:00'),
('2011-09-07T11:00:00', '2011-09-07T13:00:00'),
('2011-09-07T13:00:00', '2011-09-07T18:00:00'),
('2011-09-09T08:00:00', '2011-09-09T08:30:00'),
('2011-09-09T11:00:00', '2011-09-09T13:00:00'),
('2011-09-09T13:00:00', '2011-09-09T18:00:00'),
('2011-09-09T08:00:00', '2011-09-10T08:30:00')

declare @from varchar(5) = '09:00'
declare @to varchar(5) = '17:00'

;with L(MinDate, MaxDate) as
(
  select dateadd(day, datediff(day, 0, min(startDateTime)), 0),
         dateadd(day, datediff(day, 0, max(endDateTime)), 0)
  from @Interval
), 
D(fromTime, endTime) as
(
  select dateadd(day, Number.number, L.MinDate)+cast(@from as datetime),
         dateadd(day, Number.number, L.MinDate)+cast(@to as datetime)
  from L
    inner join master..spt_values as Number
      on Number.number <= datediff(day, L.MinDate, L.MaxDate)
  where Number.type = 'P'
)
select I.startDateTime,
       I.endDateTime
from @Interval as I
where exists (select *
              from D
              where I.startDateTime < D.endTime and
                    I.endDateTime > D.fromTime)

结果:

startDateTime           endDateTime
----------------------- -----------------------
2011-09-07 11:00:00.000 2011-09-07 13:00:00.000
2011-09-07 13:00:00.000 2011-09-07 18:00:00.000
2011-09-09 11:00:00.000 2011-09-09 13:00:00.000
2011-09-09 13:00:00.000 2011-09-09 18:00:00.000
2011-09-09 08:00:00.000 2011-09-10 08:30:00.000

如果您希望日期范围超过2048天,则需要使用数字表替换master..spt_values。确保数字表以0开头。

SQL Server 2008版本

;with L(MinDate, MaxDate) as
(
  select cast(min(startDateTime) as date),
         cast(max(endDateTime) as date)
  from @Interval
), 
D(fromTime, endTime) as
(
  select dateadd(day, Number.number, L.MinDate)+cast(@from as datetime),
         dateadd(day, Number.number, L.MinDate)+cast(@to as datetime)
  from L
    inner join master..spt_values as Number
      on Number.number <= datediff(day, L.MinDate, L.MaxDate)
  where Number.type = 'P'
)
select I.startDateTime,
       I.endDateTime
from @Interval as I
where exists (select *
              from D
              where I.startDateTime < D.endTime and
                    I.endDateTime > D.fromTime)