鉴于以下示例查询,在给定一组要排除的范围的情况下,计算日期范围内的总天数的声音和执行方法是什么,假设这些范围可能具有重叠的日期?
更简单地说,我有一个表格,其中包含一组日期范围,其中关闭计费,我从一个日期范围(比如Jan1 - Jan31)开始,我需要确定该范围内发生了多少可计费天数。只是日期的日期减去残疾人日期的日期总和。但是,残疾日期范围有可能重叠,即在一个记录中禁用1月5日至1月8日,在另一个记录中禁用1月7日至1月10日 - 因此简单的金额将在1月7日重复计算。排除这些重叠并获得准确计数的最佳方法是什么。
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
答案 0 :(得分:2)
就我而言,试过这个并且工作正常。
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
从答案https://stackoverflow.com/a/7825036/341117中获取帮助以填写日期范围
的表格答案 1 :(得分:2)
您可以使用recursive CTE生成@dateFrom
和@dateTo
之间的日期。然后将日期与范围进行比较,并查找任何范围内的所有日期。最后,计算结果中的行数以获取禁用日期的计数(DEMO):
-- recursive CTE to generate dates
;with dates as (
select @fromDate as date
union all
select dateadd(day, 1, date)
from dates
where date < @toDate
)
-- join with disable ranges to find dates in any range
, disabledDates as (
select date from dates D
left join @disableranges R
on D.date >= R.disableFrom and d.Date < R.disableTo
group by date
having count(R.disablefrom) >= 1
)
-- count up the total disabled dates
select @disabledDays=count(*) from disabledDates;