在SQL Server中递归生成日期

时间:2017-06-02 12:15:09

标签: sql sql-server sql-server-2005

我有一些我想要计算的日期,目前在几个子查询中完成。每个后续子查询在其计算中使用上一个查询的结果(日期)。 E.g。

DECLARE @Date DATE = '20170101'

SELECT @foo1 = (SELECT TOP 1 dbo.DateFunction(DateField) 
                FROM [DateTable]
                WHERE DateField <= @Date
                ORDER BY DateField DESC)

SELECT @foo2 = (SELECT TOP 1 dbo.DateFunction(DateField) 
                FROM [DateTable]
                WHERE DateField <= @foo1
                ORDER BY DateField DESC)

....

SELECT @fooN = (SELECT TOP 1 dbo.DateFunction(DateField) 
                FROM [DateTable]
                WHERE DateField <= @fooNMinus1
                ORDER BY DateField DESC)

是否有可能(可能使用CTE)进行递归查询以达到指定次数?

3 个答案:

答案 0 :(得分:0)

几周总是7天,所以你可以得到第一个,然后再加7天。如果是这样的话:

WITH dates as (
      SELECT MAX(dbo.DateFunction(DateField)) as dte, 1 as counter
      FROM [DateTable]
      WHERE DateField <= @Date
      UNION ALL
      SELECT DATEADD(DAY, 7, dte), counter + 1
      FROM dates
      WHERE counter < @n
     )
SELECT dte
FROM dates;

答案 1 :(得分:0)

您可以使用下面的小计数表

Declare @d1 date = '2017-01-01'
Declare @d2 date = '2017-12-31' 

select top (datediff(day, @d1, @d2)+1) dt = DateAdd(day, Row_Number() over (order by (Select NULL))-1, @d1) 
from master..spt_values s1, master..spt_values s2

或自定义计数表

;with num as 
( select * from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) v(n) )
, n1 as (select n1.* from num n1, num n2, num n3, num n4) --numbers generation
select top (datediff(day, @d1, @d2)+1) dt = DateAdd(day, Row_Number() over (order by (Select NULL))-1, @d1) 
from n1

答案 2 :(得分:0)

是的,您可以使用递归查询。由于递归部分中不允许使用top和聚合,因此可以使用row_number()函数。

Declare @date date = cast(getdate() as date), @n int = 10

declare @DateTable table (DateField date)
insert into @DateTable values ('2017-05-01'),('2017-05-02'),('2017-05-03'),('2017-05-04'),('2017-05-05'),('2017-05-06'),('2017-05-07'),('2017-05-08'),('2017-05-09'),('2017-05-10'),
                        ('2017-05-11'),('2017-05-12'),('2017-05-13'),('2017-05-14'),('2017-05-15'),('2017-05-16'),('2017-05-17'),('2017-05-18'),('2017-05-19'),('2017-05-20')

;with date_rte as (
    select top 1 dbo.DateFunction(DateField) datefield, 0 recursions, cast(1 as bigint) rn
    from @dateTable
    where datefield <= @date
    order by datefield desc
    union all
    select dbo.DateFunction(DateField), recursions+1, ROW_NUMBER() over (order by d.datefield desc)
    from @datetable d
    join date_rte r on d.DateField <= r.datefield
    where recursions < @n and rn = 1
)

select datefield
from date_rte 
where rn=1 and recursions = @n