2016-11-09 8 views
0

Я хочу сгенерировать семь последовательных дат с помощью CTE. Мне интересно, почему работает следующий код:SQL Server CTE puzzle

DECLARE @from DATE = '20160911', @to DATE = '20160917'; 

WITH seven_consecutive_dates AS 
(
    SELECT @from date 

    UNION ALL 

    SELECT DATEADD(DAY, 1, scd.date) 
    FROM seven_consecutive_dates scd 
    WHERE DATEADD(DAY, 1, scd.date) <= @to 
) 
SELECT * 
FROM seven_consecutive_dates 

?

и следующий не будет:

DECLARE @from DATE = '20160911', @to DATE = '20160917'; 

WITH seven_consecutive_dates AS 
(
    SELECT @from date 

    UNION ALL 

    SELECT DATEADD(DAY, 1, scd.date) 
    FROM seven_consecutive_dates scd 
    WHERE DATEDIFF(DAY, DATEADD(DAY, 1, scd.date), @to) < 6 
) 
SELECT * 
FROM seven_consecutive_dates 

Что делать, если я только начала или даты окончания? Как я могу обеспечить создание семичных последовательных дат?

+2

Поскольку для дат, предшествующих @, да тедифф меньше 6, и он постепенно уменьшается (в отрицательные числа), потому что первая дата возрастает. например dateiff (день, завтра, сегодня) равен -1, dateiff (день, через два дня, сегодня) равен -2 и т. д. Отрицательные числа меньше 6. Чтобы исправить это, измените '< 6' to '> = 0'. – ZLK

+0

Просто добавьте его в свой список 'SELECT' для его отладки http://rextester.com/DYDPOC85714 –

ответ

0

Я использую TVF для создания динамических диапазонов даты и времени. Быстрее, чем рекурсивный CTE и вы определяете диапазон дат, DATEPART и приращение

Так, например:

Select * from [dbo].[udf-Range-Date]('20160911','20160917','DD',1) 

Возвращает

RetSeq RetVal 
1  2016-09-11 00:00:00.000 
2  2016-09-12 00:00:00.000 
3  2016-09-13 00:00:00.000 
4  2016-09-14 00:00:00.000 
5  2016-09-15 00:00:00.000 
6  2016-09-16 00:00:00.000 
7  2016-09-17 00:00:00.000 

ОДСА, если интересно

CREATE FUNCTION [dbo].[udf-Range-Date] (@R1 datetime,@R2 datetime,@Part varchar(10),@Incr int) 
Returns Table 
Return (
    with cte0(M) As (Select 1+Case @Part When 'YY' then DateDiff(YY,@R1,@R2)/@Incr When 'QQ' then DateDiff(QQ,@R1,@R2)/@Incr When 'MM' then DateDiff(MM,@R1,@R2)/@Incr When 'WK' then DateDiff(WK,@R1,@R2)/@Incr When 'DD' then DateDiff(DD,@R1,@R2)/@Incr When 'HH' then DateDiff(HH,@R1,@R2)/@Incr When 'MI' then DateDiff(MI,@R1,@R2)/@Incr When 'SS' then DateDiff(SS,@R1,@R2)/@Incr End), 
     cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)), 
     cte2(N) As (Select Top (Select M from cte0) Row_Number() over (Order By (Select NULL)) From cte1 a, cte1 b, cte1 c, cte1 d, cte1 e, cte1 f, cte1 g, cte1 h), 
     cte3(N,D) As (Select 0,@R1 Union All Select N,Case @Part When 'YY' then DateAdd(YY, N*@Incr, @R1) When 'QQ' then DateAdd(QQ, N*@Incr, @R1) When 'MM' then DateAdd(MM, N*@Incr, @R1) When 'WK' then DateAdd(WK, N*@Incr, @R1) When 'DD' then DateAdd(DD, N*@Incr, @R1) When 'HH' then DateAdd(HH, N*@Incr, @R1) When 'MI' then DateAdd(MI, N*@Incr, @R1) When 'SS' then DateAdd(SS, N*@Incr, @R1) End From cte2) 

    Select RetSeq = N+1 
      ,RetVal = D 
    From cte3,cte0 
    Where D<[email protected] 
) 
/* 
Max 100 million observations -- Date Parts YY QQ MM WK DD HH MI SS 
Syntax: 
Select * from [dbo].[udf-Range-Date]('2016-10-01','2020-10-01','YY',1) 
Select * from [dbo].[udf-Range-Date]('2016-01-01','2017-01-01','MM',1) 
*/ 
Смежные вопросы