Return 基于 SQL 中两个给定日期之间给定间隔的日期范围

Return Date Ranges based based on a given interval between two given dates in SQL

我正在尝试获取两个日期之间给定间隔的所有 DateRanges 的列表。

例如,如果我有日期 2015-04-01 和 2015-06-20,当间隔为 20 时,结果应该是

DateFrom       DateTo
------------------------
2015-04-01  2015-04-21
2015-04-22  2015-05-12
2015-05-13  2015-06-02
2015-06-03  2015-06-20
-------------------

这是我正在尝试的查询

DECLARE @StartDateTime DATETIME
DECLARE @EndDateTime DATETIME
DECLARE @Interval int = 20
SET @StartDateTime = '2015-04-01'
SET @EndDateTime = '2015-06-20';

WITH DateRange(DateStart,DateEnd) AS 
(
    SELECT @StartDateTime, DATEADD(d,@Interval,@StartDateTime)
    UNION ALL
    SELECT DATEADD(d,1,DateEnd), DATEADD(d,@Interval,DateEnd)
    FROM DateRange 
    WHERE DateEnd <= @EndDateTime
)
SELECT CAST(DateStart as date) DateStart
    , CAST(DateEnd as Date) DateEnd
FROM DateRange
OPTION (MAXRECURSION 0)
GO

它返回以下结果,这与我上面的预期结果不完全相同

DateStart   DateEnd
2015-04-01  2015-04-21
2015-04-22  2015-05-11
2015-05-12  2015-05-31
2015-06-01  2015-06-20
2015-06-21  2015-07-10

如您所见,在给定日期之外还有一行,第二行之后的间隔是 19 天,而不是 20 天。我理解它是因为我在 [= 之后的第一个字段中添加了一天27=]联合所有

请帮我解决这个问题,或者请提出更好的实现方法。

递归 cte 的更改应该是

使用 CASE 检查结束日期。如果大于要求的结束日期,则将其设置为 @EndDateTime

另外WHERE条件应该是

WHERE DateEnd < @EndDateTime


WITH DateRange(DateStart,DateEnd) AS 
( 

SELECT @StartDateTime,DATEADD(day, @Interval, @StartDateTime)

UNION ALL

SELECT dateadd(day, 1, DateEnd), 
       case when DATEADD(day, @Interval + 1, DateEnd) <= @EndDateTime
            then DATEADD(day, @Interval + 1, DateEnd)
            else @EndDateTime
            end
FROM  DateRange 
WHERE DateEnd < @EndDateTime

)

如果您希望每隔 @Interval 天开始一​​次间隔

DECLARE @StartDateTime DATETIME
DECLARE @EndDateTime DATETIME
declare @Interval int=20
SET @StartDateTime = '2015-04-01'
SET @EndDateTime = '2015-06-20';

WITH DateRange(DateStart,DateEnd) AS 
(
    SELECT @StartDateTime, DATEADD(d, @Interval - 1, @StartDateTime)
    UNION ALL
    SELECT dateadd(d, @Interval, DateStart),DATEADD(d, @Interval, DateEnd)
    FROM DateRange 
    WHERE DateEnd < @EndDateTime - 1
)
SELECT cast(DateStart as date) DateStart,cast(DateEnd as Date) DateEnd
FROM DateRange
OPTION (MAXRECURSION 0)