Sql server 查找日期范围中的差距-TSQL

Sql server 查找日期范围中的差距-TSQL,sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,我有下面的SQL,我想在下面的日期差距 declare @startdate datetime = '2017-05-01' declare @enddate datetime = '2017-05-25' create table #tmpdates (id int, date1 datetime, date2 datetime, rate int) insert into #tmpdates values (1, '2017-05-05', '2017-05-15', 10) inser

我有下面的SQL,我想在下面的日期差距

declare @startdate datetime = '2017-05-01'
declare @enddate datetime = '2017-05-25'

create table #tmpdates (id int, date1 datetime, date2 datetime, rate int)

insert into #tmpdates values (1, '2017-05-05', '2017-05-15', 10)
insert into #tmpdates values (2, '2017-05-16', '2017-05-18', 12)
insert into #tmpdates values (3, '2017-05-21', '2017-05-25', 15)

select * from #tmpdates where date1 >= @startdate and date2 <= @enddate

drop table #tmpdates

在我上面的查询中,只有日期范围记录返回。。请指导,或者我如何将这些也包括在内?

这是在假设没有重叠间隔的情况下工作的

declare @startdate datetime = '2017-05-16'
declare @enddate datetime = '2017-05-26'

create table #tmpdates (id int, date1 datetime, date2 datetime, rate int)

insert into #tmpdates values (0, '2017-04-01', '2017-04-25',22)
insert into #tmpdates values (1, '2017-05-05', '2017-05-15', 10)
insert into #tmpdates values (2, '2017-05-16', '2017-05-18', 12)
insert into #tmpdates values (3, '2017-05-21', '2017-05-25', 15)

declare @final_result table (date1 date, date2 date, rate int)

insert into @final_result 

select @startdate,dateadd(day,-1,t.date1),null
from #tmpdates t
where @startdate < t.date1 and 
        t.date1 <= (select min(t1.date1) from #tmpdates t1 where t1.date1 >= @startdate)

union all

select date1, date2, rate 
from #tmpdates 
where (date1 >= @startdate or date2 >= @startdate) and 
      (date2 <= @enddate or date1 <= @enddate)

union all

select dateadd(day,1,t.date2), 
        ( select dateadd(day,-1,min(t3.date1)) 
            from #tmpdates t3 where t3.date1 > t.date2) , 
        null
from #tmpdates t
where dateadd(day,1,t.date2) < (select min(t1.date1) from #tmpdates  t1 where t1.date1 > t.date2)
and t.date1 >= @startdate and t.date2 <= @enddate

union all

select dateadd(day,1,max(t.date2)), @enddate, null
from #tmpdates t
having max(t.date2) < @enddate


drop table #tmpdates

select * from @final_result order by date1
如果@startdate之前有间隔,则选择@startdate与表中第一个最小日期之间的间隔。因此,它选择了从@startdate到大于@startdate的间隔的第一个日期之间的间隔(如果有)

第二个问题:

选择表中@startdate和@enddate间隔之间的最小和最大间隙

最后是第四个问题:

选择最大日期之间的间隔表上@startdate和@enddate之间的最大日期和@enddate之间的间隔(如果有间隔)


所有这些记录都插入到@final_result表中,以便按时间间隔排序。

您可以尝试下面的代码。我从@StartDate一直走到@endDate,找到了缺口

declare @startdate datetime = '2017-05-01'
declare @enddate datetime = '2017-05-04'
declare @startdate1 datetime, @enddate1 datetime
declare @dates table (date1 date,date2 date)
create table #tmpdates (id int, date1 datetime, date2 datetime, rate int)

insert into #tmpdates values (1, '2017-05-05', '2017-05-15', 10)
insert into #tmpdates values (2, '2017-05-16', '2017-05-18', 12)
insert into #tmpdates values (3, '2017-05-21', '2017-05-25', 15)

select * from #tmpdates where date1 >= @startdate and date2 <= @enddate
set @startdate1=@startdate
while @startdate1<=@enddate
begin
     if not exists(select 1 from #tmpdates where @startdate1 between date1 and date2)
     begin
          if not exists (select 1 from @dates where @startdate1 > date1 and date2 is null)
          begin
               insert into @dates(date1)values(@startdate1)
          end
          else
          begin
               if @startdate1+1>=@enddate
               begin
                   update @dates set date2=@startdate1 where date2 is null
               end
               set @startdate1+=1
          end
     end
     else
     begin 
         update @dates set date2=@startdate1-2 where date2 is null
     end
     set @startdate1+=1       
end
select * from
(select date1,date2, rate from #tmpdates
union
select *,0  as rate from @dates
) A WHERE date1>=@startdate and date2<=@enddate
drop table #tmpdates

请使用以下查询:

DECLARE @STARTDATE DATE = '2017-05-01'
DECLARE @ENDDATE DATE = '2017-05-25'

DECLARE @DATES TABLE (ID INT, DATE1 DATE, DATE2 DATE, RATE INT)

INSERT INTO @DATES VALUES 
(1, '2017-05-05', '2017-05-15', 10),
(2, '2017-05-16', '2017-05-19', 12),
(3, '2017-05-21', '2017-05-25', 15)

SELECT* FROM 
(
    SELECT @STARTDATE AS DATE1,DATEADD(DAY,-1,MIN(DATE1)) AS DATE2,'NO DATA'AS RATE FROM @DATES
    UNION
    SELECT 
    CASE WHEN   
            LEAD(DATE1) OVER (ORDER BY DATE1) = DATEADD(DAY,1,DATE2) THEN NULL 
            ELSE DATEADD(DAY,1,DATE2) END AS DATE1,
    CASE WHEN   
            LEAD(DATE1) OVER (ORDER BY DATE1) = DATEADD(DAY,1,DATE2) THEN NULL 
            ELSE LEAD(DATEADD(DAY,-1,DATE1)) OVER (ORDER BY DATE1) END AS DATE2,
    'NO DATA'AS RATE
    FROM @DATES d
    UNION
    SELECT DATE1, DATE2,CAST(RATE AS NVARCHAR(10)) FROM @DATES
    UNION
    SELECT DATEADD(DAY,1,MAX(DATE2)) AS DATE1,@ENDDATE AS DATE2,'NO DATA'AS RATE FROM @DATES
) A WHERE A.DATE2 IS NOT NULL AND A.DATE1 <= A.DATE2
  AND DATE1 >= @STARTDATE AND DATE2 <=@ENDDATE
ORDER BY A.DATE1

我真的很难理解你想要在这里实现什么。你能再解释一遍吗?OP有一个开始日期和结束日期,再加上一个表,表中有日期范围。他想找出表中没有的开始日期和结束日期之间的范围。@Tanner这还不够。为什么是1-4和19-20,而不是17和21-24?@tanner-谢谢你,这为我做到了:读一下:它描述了如何为@StartDate和@EndDate之间的所有日期生成行。一旦你有了这一点,将表格与中的空白连接起来。这只适用于样本数据还是适用于现实世界中更大的数据集?@Tanner I补充了对其工作原理的解释。它应该适用于任何数据集,只要我没有用它测试的时间间隔没有重叠。如果我通过declare startdate datetime='2017-05-01',declare enddate datetime='2017-06-25',最后的记录显示错误的日期范围@啊哈,我知道了。正在解决这个问题如果我添加declare startdate datetime='2017-05-06',它应该包括它的范围。如果@startdate='2017-05-01'和@enddate='2017-05-04',这不会返回一行,就像@k-s想要的那样。嗨@ahoxha,很好。我刚刚修改了代码。你现在可以检查一下了
select date1, date2, rate 
from #tmpdates 
where (date1 >= @startdate or date2 >= @startdate) and 
      (date2 <= @enddate or date1 <= @enddate)
select dateadd(day,1,t.date2), 
        ( select dateadd(day,-1,min(t3.date1)) 
            from #tmpdates t3 where t3.date1 > t.date2) , 
        null
from #tmpdates t
where dateadd(day,1,t.date2) < (select min(t1.date1) from #tmpdates  t1 where t1.date1 > t.date2)
and t.date1 >= @startdate and t.date2 <= @enddate
select dateadd(day,1,max(t.date2)), @enddate, null
from #tmpdates t
having max(t.date2) < @enddate
declare @startdate datetime = '2017-05-01'
declare @enddate datetime = '2017-05-04'
declare @startdate1 datetime, @enddate1 datetime
declare @dates table (date1 date,date2 date)
create table #tmpdates (id int, date1 datetime, date2 datetime, rate int)

insert into #tmpdates values (1, '2017-05-05', '2017-05-15', 10)
insert into #tmpdates values (2, '2017-05-16', '2017-05-18', 12)
insert into #tmpdates values (3, '2017-05-21', '2017-05-25', 15)

select * from #tmpdates where date1 >= @startdate and date2 <= @enddate
set @startdate1=@startdate
while @startdate1<=@enddate
begin
     if not exists(select 1 from #tmpdates where @startdate1 between date1 and date2)
     begin
          if not exists (select 1 from @dates where @startdate1 > date1 and date2 is null)
          begin
               insert into @dates(date1)values(@startdate1)
          end
          else
          begin
               if @startdate1+1>=@enddate
               begin
                   update @dates set date2=@startdate1 where date2 is null
               end
               set @startdate1+=1
          end
     end
     else
     begin 
         update @dates set date2=@startdate1-2 where date2 is null
     end
     set @startdate1+=1       
end
select * from
(select date1,date2, rate from #tmpdates
union
select *,0  as rate from @dates
) A WHERE date1>=@startdate and date2<=@enddate
drop table #tmpdates
DECLARE @STARTDATE DATE = '2017-05-01'
DECLARE @ENDDATE DATE = '2017-05-25'

DECLARE @DATES TABLE (ID INT, DATE1 DATE, DATE2 DATE, RATE INT)

INSERT INTO @DATES VALUES 
(1, '2017-05-05', '2017-05-15', 10),
(2, '2017-05-16', '2017-05-19', 12),
(3, '2017-05-21', '2017-05-25', 15)

SELECT* FROM 
(
    SELECT @STARTDATE AS DATE1,DATEADD(DAY,-1,MIN(DATE1)) AS DATE2,'NO DATA'AS RATE FROM @DATES
    UNION
    SELECT 
    CASE WHEN   
            LEAD(DATE1) OVER (ORDER BY DATE1) = DATEADD(DAY,1,DATE2) THEN NULL 
            ELSE DATEADD(DAY,1,DATE2) END AS DATE1,
    CASE WHEN   
            LEAD(DATE1) OVER (ORDER BY DATE1) = DATEADD(DAY,1,DATE2) THEN NULL 
            ELSE LEAD(DATEADD(DAY,-1,DATE1)) OVER (ORDER BY DATE1) END AS DATE2,
    'NO DATA'AS RATE
    FROM @DATES d
    UNION
    SELECT DATE1, DATE2,CAST(RATE AS NVARCHAR(10)) FROM @DATES
    UNION
    SELECT DATEADD(DAY,1,MAX(DATE2)) AS DATE1,@ENDDATE AS DATE2,'NO DATA'AS RATE FROM @DATES
) A WHERE A.DATE2 IS NOT NULL AND A.DATE1 <= A.DATE2
  AND DATE1 >= @STARTDATE AND DATE2 <=@ENDDATE
ORDER BY A.DATE1