2011-09-28 141 views
1

我很驚訝這還沒有出現。查找重疊的時間範圍

在T-SQL中,我需要找到與每日間隔(例如上午9點至下午5點)重疊的間隔(由startDateTime和endDateTime定義)。

例如,對於表:

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 AM - 2011年9月7日8:30 PM
  2. 2011年9月7日11:00 AM - 2011年9月7日1:00 PM
  3. 2011年9月7日1:00 PM - 2011年9月7日6:00 PM
  4. 2011年9月9日8:00 AM - 2011年9月9日8: 30 PM
  5. 2011年9月9日11:00 - 2011年9月9日下午1:00
  6. 2011年9月9日下午1:00 - 2011年9月9日下午6:00

因此,對於給定的間隔「九至五「,2,3,5和6應該返回,因爲它們與給定的輸入重疊。

但是,

  1. 2011年9月9日上午8:00 - 2011年9月10日8:30 PM

也非常適合,因爲它包含了整整一天。

請幫助我在T-SQL中匹配字符串和日期時間值,而不是抽象「少於」/「大於那麼」解決方案。

+1

[它肯定之前拿出...](http://stackoverflow.com/questions/143552/comparing-date-ranges/143568#143568) –

+0

不是。將字符串與日期時間值進行比較遠不是微不足道的。這裏的問題不是算法本身(這是微不足道的),而是如何在T-SQL中實現。 – tishma

+0

我會說相反。一旦你知道這個算法,在TSQL中實現它是微不足道的,但是從spe dude http://stackoverflow.com/q/4816323/73226 –

回答

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) 
+0

+1轉換建議。它不是100%完美,仍然夠好。謝謝。 – tishma

+0

啊!你已經用datetime替換了varchars ... – tishma

+0

@tishma - 不僅如此。它也「處理多天的時間間隔」。在帶有時間數據類型的SQL Server 2008中,解決方案完全相同。 –