Gerar datas entre intervalos de datas

Preciso preencher uma tabela que armazene os intervalos de datas entre duas datas: 09/01/11 – 10/10/11

Então, neste caso, a tabela iria começar a partir de 09/01/11 e armazenar todos os dias até chegar a 10/10/11 Eu queria saber se havia uma maneira esperta de fazer isso no SQL Server – atualmente estou usando o SQL Server 2008 . Obrigado

Fácil no SQL 2005+; mais fácil se você tiver uma tabela de números ou registro. Eu fingi abaixo:

DECLARE @StartDate DATE = '20110901' , @EndDate DATE = '20111001' SELECT DATEADD(DAY, nbr - 1, @StartDate) FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr FROM sys.columns c ) nbrs WHERE nbr - 1 < = DATEDIFF(DAY, @StartDate, @EndDate) 

Se você tiver uma tabela de registro, substitua a subconsulta pela tabela. Nenhuma recursion.

Tente isso se você estiver usando o SQL Server 2005 ou mais recente:

 WITH Dates AS ( SELECT [Date] = CONVERT(DATETIME,'09/01/2011') UNION ALL SELECT [Date] = DATEADD(DAY, 1, [Date]) FROM Dates WHERE Date < '10/10/2011' ) SELECT [Date] FROM Dates OPTION (MAXRECURSION 45) 

Um bom exemplo de coisas legais que você pode fazer com um CTE.

Declarações

 DECLARE @dates TABLE(dt datetime) DECLARE @dateFrom datetime DECLARE @dateTo datetime SET @dateFrom = '2001/01/01' SET @dateTo = '2001/01/12' 

Consulta:

 WHILE(@dateFrom < @dateTo) BEGIN SELECT @dateFrom = DATEADD(day, 1,@dateFrom) INSERT INTO @dates SELECT @dateFrom END 

- saída

 SELECT * FROM @dates 

Use a function F_TABLE_DATE do MVJ, é puramente incrível:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=61519

Depois de implementar isso, basta passar na data de início e fim e você pode inserir todas as datas entre.

Aqui está uma solução que não requer recursion e, ao mesmo tempo, essa function com valor de tabela é reutilizável em muitas consultas sem a necessidade de repetir a declaração de variables ​​padronizadas novamente. Esta é a única alternativa, para aqueles que não querem recursion.

Crie esta function simples:

 CREATE FUNCTION [dbo].[GenerateDateRange] (@StartDate AS DATE, @EndDate AS DATE, @Interval AS INT ) RETURNS @Dates TABLE(DateValue DATE) AS BEGIN DECLARE @CUR_DATE DATE SET @CUR_DATE = @StartDate WHILE @CUR_DATE < = @EndDate BEGIN INSERT INTO @Dates VALUES(@CUR_DATE) SET @CUR_DATE = DATEADD(DAY, @Interval, @CUR_DATE) END RETURN; END; 

E então selecione por:

 select * from dbo.GenerateDateRange('2017-01-03', '2017-12-01', 1) 

Usando a resposta de @Abe Miesler, para conveniência de outros, eu o construí em um TVF para o SQL Server 2008 em diante. Pode ajudar os outros – eu tive que encontrar uma maneira de include o CTE dentro do TVF!

  --Generate a range of dates with interval option, courtesy of Abe Miessler for the core query here! ALTER FUNCTION [dbo].[DateRange] (@startDate AS DATE, @EndDate AS DATE, @interval AS INT ) RETURNS @Dates TABLE(dateValue DATE) AS BEGIN WITH Dates AS ( SELECT [Date] = CONVERT( DATETIME, @startDate) UNION ALL SELECT [Date] = DATEADD(DAY, ISNULL(@interval, 1), [Date]) FROM Dates WHERE Date < @EndDate) INSERT INTO @Dates SELECT [Date] FROM Dates OPTION(MAXRECURSION 900); RETURN; END; 
 Declare @StartDate datetime = '2015-01-01' Declare @EndDate datetime = '2016-12-01' declare @DaysInMonth int declare @tempDateRange Table ( DateFrom datetime, DateThru datetime ); While @StartDate< =@EndDate begin SET @DaysInMonth=DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,@StartDate),0))) IF DAY(@StartDate)=1 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=30 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=31 SET @EndDate=DATEADD(DAY,15,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=28 SET @EndDate=DATEADD(DAY,12,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=29 SET @EndDate=DATEADD(DAY,13,@StartDate) INSERT INTO @tempDateRange (DateFrom,DateThru) VALUES ( @StartDate, @EndDate ) SET @StartDate=DATEADD(DAY,1,@EndDate) IF @EndDate< '2016-12-31' IF DAY(@StartDate)=1 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=30 SET @EndDate=DATEADD(DAY,14,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=31 SET @EndDate=DATEADD(DAY,15,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=28 SET @EndDate=DATEADD(DAY,12,@StartDate) ELSE IF DAY(@StartDate)=16 AND @DaysInMonth=29 SET @EndDate=DATEADD(DAY,13,@StartDate) end ; select * from @tempDateRange +++++++++++++++++++++++++++++ Result: DateFrom |DateThru 

Se por algum motivo você não puder declare variables, como ao usar tabelas derivadas no Looker , você pode ir assim:

 select dateadd(day, nbr - 1, convert(date, '2017-01-01')) as d from ( select row_number() over (order by c.object_id) as nbr from sys.columns c ) nbrs where nbr - 1 < = datediff( day, convert(date, '2017-01-01'), convert(date, '2018-12-31') ) 

Aliás, é assim que a visualização da série de datas pode parecer no LookerML:

 view: date_series { derived_table: { sql: select dateadd(day, nbr - 1, convert(date, '2017-01-01')) as d from ( select row_number() over (order by c.object_id) as nbr from sys.columns c ) nbrs where nbr - 1 < = datediff(day, convert(date, '2017-01-01'), convert(date, '2018-12-31')) ;; } dimension: date { primary_key: yes type: date sql: ${TABLE}.d ;; } }