如何在不使用CTE的情况下从日期范围创建日期列表

时间:2012-10-31 11:08:05

标签: sql sql-server stored-procedures

以下链接说明如何将日期范围转换为日期列表。 我使用这种方法,它工作正常,但查询没有执行(我使用Maxrecursion 0无限制)。

http://blog.justinstolle.com/sql-turn-a-date-range-into-a-list-of-dates/

还有其他方法可以完成这项工作吗? (使用子查询或声明表?)

2 个答案:

答案 0 :(得分:3)

尝试

declare @datestart date = '2012-1-1',   @dateend date = '2012-10-31'

declare @days int = datediff(d,@datestart,@dateend)

select
    dateadd(d, number, @datestart)
from master..spt_values 
where type='p'
    and number<=@days

如果您的日期范围超过2047天,您可以通过自行加入表格来扩展它 - 以下将允许您长达27年..

select
    dateadd(d, v1.number+v2.number*2048, @datestart)
from master..spt_values v1
    cross join (select number from master..spt_values where number<5 and type='p') v2       
where type='p'
    and (v1.number+v2.number*2048)<=@days

答案 1 :(得分:-1)

这是链接中的相同查询,稍作修改(使用CTE)。请检查:

DECLARE @dateranges TABLE (range_id VARCHAR(2), date_begin DATETIME, date_end DATETIME)
INSERT @dateranges SELECT 'A', '2010-01-01', '2010-01-03'
INSERT @dateranges SELECT 'B', '2008-02-27', '2008-03-01'
INSERT @dateranges SELECT 'C', '2010-04-26', '2010-04-26'
INSERT @dateranges SELECT 'D', '2000-02-01', '2001-02-05'

;WITH cte (id, d)
AS (SELECT tbl.range_id AS id, tbl.date_begin AS d
    FROM @dateranges tbl
    WHERE DATEDIFF(DAY, tbl.date_begin, tbl.date_end) >0
    UNION ALL
    SELECT tbl.range_id AS id, DATEADD(DAY, 1, cte.d) AS d
    FROM cte INNER JOIN @dateranges tbl
    ON cte.id = tbl.range_id
    WHERE cte.d < tbl.date_end)
SELECT id AS range_id, d AS date_within_range FROM cte
ORDER BY id, d
OPTION (MAXRECURSION 0);