99,99999% das pessoas que trabalham com banco de dados tem ao menos uma tabela que tem duas colunas: Data de ínicio e data de fim (estatística baseada em mero chute, sem embasamento algum).
A questão é:
Eu tenho essa data de início e data de fim, como eu faço para retornar, em linhas distintas, o range que compreende essas datas?
Seria algo como:
O que eu preciso: retornar, em uma coluna, o período (dias, semanas, meses, anos) que compreende as datas iniciais e finais.
Para isso, vamos usar o conceito de CTE’s (Common Table Expressions) recursivas.
Primeiro, precisamos pegar o menor valor correspondente para cada registro, que vai servir como base (a.k.a. âncora) para a recursão.
SELECT Codigo, Nome, min(datainicial) data FROM RangeSeq GROUP BY Codigo, nome
Agora, colocamos essa query em uma CTE e chamamos ela várias vezes, até chegarmos no limite para cada registro:
;with cte_range as
(
SELECT Codigo, Nome, min(datainicial) data
FROM RangeSeq
GROUP BY Codigo, nome
UNION ALL -- Aqui é onde a mágica da recursão começa...
SELECT c.Codigo, c.Nome, DATEADD(DAY,1,c.data)
From RangeSeq r
join cte_range c -- Aqui é onde eu estou chamando a própria CTE (a recursão)
on r.Codigo = c.Codigo
where c.data < r.DataFinal -- No where, eu preciso determinar quando o processamento deve parar
-- Para que não entre em loop
)
select * from cte_range
order by Codigo, data
option (maxrecursion 1500) -- A CTE recursiva tem um limite de 100 iterações. Com esta opção eu
-- mudo o limite. Coloque 0 (zero) para que não exista limite.Vejamos o resultado (resumido, pois são mais de 1200 linhas retornadas):