Sql server 使用一组可能重叠的排除项计算日期范围内的天数

Sql server 使用一组可能重叠的排除项计算日期范围内的天数,sql-server,tsql,Sql Server,Tsql,在下面的查询示例中,考虑到某个日期范围可能有重叠的日期,当给定一组要排除的范围时,计算该日期范围内的总天数的合理且有效的方法是什么 更简单地说,我有一个表,表中有一组日期范围,在这些日期范围内,账单被关闭,我从一个日期范围开始,比如说1月1日到1月31日,我需要确定在这个范围内发生了多少计费日。简单地说,是天数的datediff减去残疾天数的datediff之和。但是,禁用日期范围有可能重叠,即在一条记录中禁用了Jan5-Jan8,在另一条记录中禁用了Jan7-Jan10,因此一个简单的总和将加

在下面的查询示例中,考虑到某个日期范围可能有重叠的日期,当给定一组要排除的范围时,计算该日期范围内的总天数的合理且有效的方法是什么

更简单地说,我有一个表,表中有一组日期范围,在这些日期范围内,账单被关闭,我从一个日期范围开始,比如说1月1日到1月31日,我需要确定在这个范围内发生了多少计费日。简单地说,是天数的datediff减去残疾天数的datediff之和。但是,禁用日期范围有可能重叠,即在一条记录中禁用了Jan5-Jan8,在另一条记录中禁用了Jan7-Jan10,因此一个简单的总和将加倍计算Jan7。排除这些重叠并获得准确计数的最佳方法是什么

Declare @disableranges table (disableFrom datetime, disableTo datetime)
insert into @disableranges
select '01/05/2013', '01/08/2013' union
select '01/07/2013', '01/10/2013' union
select '01/15/2013', '01/20/2013'

declare @fromDate datetime = '01/01/2013'
declare @toDate datetime = '01/31/2013'

declare @totalDays int = DATEDIFF(day,@fromDate,@toDate)
declare @disabledDays int = (0 /*not sure best way to calc this*/)

select @totalDays - @disabledDays

就我而言,我试过了,工作正常

Declare @disableranges table (disableFrom datetime, disableTo datetime)
insert into @disableranges
select '01/05/2013', '01/08/2013' union
select '01/07/2013', '01/10/2013' union
select '01/15/2013', '01/20/2013'

declare @fromDate datetime = '01/01/2013'
declare @toDate datetime = '01/31/2013'

declare @totalDays int = DATEDIFF(day,@fromDate,@toDate) + 1 /*Without +1 it is giving 30 instead of 31*/
declare @disabledDays int = (0 /*not sure best way to calc this*/)
/*Fill temporary table with the given date range.*/
SELECT  DATEADD(DAY, nbr - 1, @fromDate) TempDate INTO #Temp
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
          FROM      sys.columns c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(DAY, @fromDate, @toDate)
/*Check how many dates exists in the disableranges table*/
SELECT @disabledDays=count(*) from #Temp t WHERE 
EXISTS(SELECT * FROM @disableranges 
WHERE t.TempDate BETWEEN disableFrom AND DATEADD(d, -1, disableTo))

select @totalDays /*Output:31*/
select @disabledDays /*Output:10*/
select @totalDays - @disabledDays /*Output:21*/
drop table #Temp

从答案中获取帮助,用日期范围填充表格

尝试了这个,就我而言,工作正常

Declare @disableranges table (disableFrom datetime, disableTo datetime)
insert into @disableranges
select '01/05/2013', '01/08/2013' union
select '01/07/2013', '01/10/2013' union
select '01/15/2013', '01/20/2013'

declare @fromDate datetime = '01/01/2013'
declare @toDate datetime = '01/31/2013'

declare @totalDays int = DATEDIFF(day,@fromDate,@toDate) + 1 /*Without +1 it is giving 30 instead of 31*/
declare @disabledDays int = (0 /*not sure best way to calc this*/)
/*Fill temporary table with the given date range.*/
SELECT  DATEADD(DAY, nbr - 1, @fromDate) TempDate INTO #Temp
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
          FROM      sys.columns c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(DAY, @fromDate, @toDate)
/*Check how many dates exists in the disableranges table*/
SELECT @disabledDays=count(*) from #Temp t WHERE 
EXISTS(SELECT * FROM @disableranges 
WHERE t.TempDate BETWEEN disableFrom AND DATEADD(d, -1, disableTo))

select @totalDays /*Output:31*/
select @disabledDays /*Output:10*/
select @totalDays - @disabledDays /*Output:21*/
drop table #Temp
从答案中获取帮助,用日期范围填充表格

您可以使用来生成@dateFrom和@dateTo之间的日期。然后将日期与范围进行比较,找出任何范围内的所有日期。最后,计算结果中的行数以获得禁用日期的计数:

您可以使用生成介于@dateFrom和@dateTo之间的日期。然后将日期与范围进行比较,找出任何范围内的所有日期。最后,计算结果中的行数以获得禁用日期的计数:


禁用范围是否包括在内?i、 例如,2013年5月1日至2013年8月1日是3天还是4天?默认情况下,只调用DATEDIFF将包括开始日期,但不包括结束日期,因为默认时间值为0:00:00 midnight。在我看来,这也算3,只有您知道它应该是什么:。问题是,当你说禁用范围为2013年5月1日至2013年8月1日时,这是否意味着第8个日期也包括在内?不,就我而言,第二个日期是“禁用到”的日期,意味着该日期不再禁用。所以第八个不算。禁用范围包括在内吗?i、 例如,2013年5月1日至2013年8月1日是3天还是4天?默认情况下,只调用DATEDIFF将包括开始日期,但不包括结束日期,因为默认时间值为0:00:00 midnight。在我看来,这也算3,只有您知道它应该是什么:。问题是,当你说禁用范围为2013年5月1日至2013年8月1日时,这是否意味着第8个日期也包括在内?不,就我而言,第二个日期是“禁用到”的日期,意味着该日期不再禁用。所以第八个不算。