以下處理反轉日期範圍並正確處理與目標範圍的開始和/或結束重疊的範圍。 編輯:已更新,以處理未找到適用範圍的情況。
declare @DateRanges as Table (Id Int Identity, SDate Date, EDate Date);
insert into @DateRanges (SDate, EDate) values
('20130105', '20130112'),
('20130113', '20130118'),
('20130205', '20130312'),
('20130708', '20130831'),
-- Additional test data for ranges that overlap the target date range, or not.
('20100101', '20130101'),
('20131127', '20140102'),
('19990208', '20041118'),
('20601113', '20990101');
select * from @DateRanges order by SDate;
declare @StartDate as Date = '20130101';
declare @EndDate as Date = DateAdd(day, -1, DateAdd(year, 1, @StartDate));
select @StartDate as [@StartDate], @EndDate as [@EndDate];
with SortedDateRanges as (
-- Sort the date ranges so that we have a dense row number for later use.
select SDate, EDate, Row_Number() over (order by SDate) as RN
from @DateRanges
where EDate >= @StartDate and SDate <= @EndDate),
PairedDateRanges as (
-- Pair the adjacent date ranges and turn them inside out.
select DateAdd(day, 1, L.EDate) as SDate, DateAdd(day, -1, R.SDate) as EDate
from SortedDateRanges as L inner join
SortedDateRanges as R on R.RN = L.RN + 1)
-- The result is all of inside out date ranges that are valid, i.e. don't end before they start...
select SDate, EDate, 'Fill Gap' as Reason
from PairedDateRanges
where SDate <= EDate
union
-- ... plus any leading date range ...
select @StartDate, DateAdd(day, -1, SDate), 'Leading'
from SortedDateRanges
where RN = 1 and SDate > @StartDate
union
-- ... plus any trailing date range ...
select DateAdd(day, 1, EDate), @EndDate, 'Trailing'
from SortedDateRanges
where RN = (select Max(RN) from SortedDateRanges) and EDate < @EndDate
union
-- ... or we have nothing.
select @StartDate, @EndDate, 'No Data'
where not exists (select 42 from SortedDateRanges)
order by SDate;
我的簡短答案中缺少的是什麼? –