递归CTE返回的值超出范围

时间:2018-09-20 20:55:45

标签: sql sql-server sql-server-2008

在寻找一种创建日期范围的方法时,我遇到了以下查询的问题:

DECLARE @StartDate DateTime = '2000-01-01 01:00';
DECLARE @EndDate DateTime = '2020-01-01 00:00';

with Dates as (
  select
  @StartDate fromDate
  UNION ALL
  (Select
     fromDate = dateadd(day, 1, @EndDate)
   from
     Dates
   where
     fromDate >= @StartDate AND
     fromDate < @EndDate ))

Select * from Dates
OPTION (MAXRECURSION 0);

以下查询返回两行,其中之一不在范围内,

fromDate
-----------------------
2000-01-01 01:00:00.000
2020-01-02 00:00:00.000

我知道可以通过将查询的后半部分更改为不同的方式来解决此问题,例如:

Select * from Dates Where fromDate <= @EndDate 

我有以下问题:

  • 查询本身有什么问题?
  • 此查询为什么返回两个值,其中一个值不在提供的范围内?

这是使用Microsoft SQL Server 2008 R2

2 个答案:

答案 0 :(得分:3)

因为您的Recursive CTEfromDate开始有一天

Select
     fromDate = dateadd(day, 1, @EndDate)

但是您的条件过滤器fromDate

where
     fromDate >= @StartDate AND
     fromDate < @EndDate ))

如果要通过Recursive CTE制作日历表。

您可以尝试一下。

with Dates as (
  select @StartDate fromDate,@EndDate endDate
  UNION ALL
  Select
     fromDate = dateadd(day, 1, fromDate),endDate
   from
     Dates
   where
      dateadd(day, 1, fromDate) <= @EndDate 
)
Select * from Dates
OPTION (MAXRECURSION 0);

答案 1 :(得分:0)

#1 /#2的简单答案:您正在选择DATEADD(day,1,@endDate),根据定义,这是您的日期范围“超出” 1天。

真正的答案:要获得所需的结果,请更改:

(Select
    fromDate = dateadd(day, 1, @EndDate)

收件人:

(Select
    fromDate = dateadd(day, 1, fromDate)