如何列出两个日期之间的所有日期

26

我希望在SQL Server存储过程中列出两个日期之间的所有日期。

例如:

Date1: 2015-05-28
Date2: 2015-05-31

结果:

2015-05-29
2015-05-30

如何计算两个给定日期之间的所有日期?

敬礼,


http://www.sqlperformance.com/2013/01/t-sql-queries/generate-a-set-3 - Aaron Bertrand
5个回答

49
您可以使用数字表格:
DECLARE @Date1 DATE, @Date2 DATE
SET @Date1 = '20150528'
SET @Date2 = '20150531'

SELECT DATEADD(DAY,number+1,@Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY,number+1,@Date1) < @Date2

结果:

╔════════════╗
║    Date    ║
╠════════════╣
║ 2015-05-29 ║
║ 2015-05-30 ║
╚════════════╝

3
我不会这样做。万一我无法访问“主分支”怎么办? - Luis LL
1
@LuisLL 这只是一个数字表的快速示例,op可以使用任何其他表,或者日历表。通常比递归CTE更快(尽管我喜欢使用它们,但我知道它们会带来性能问题)。 - Lamak
2
如果您需要获取长达15-20年的日期范围,则会有限制。因为它使用了表master..spt_values。 - gmsi
由于spt_values的值范围仅限于0-2047,因此不是万无一失的。 - caiosm1005
这是大多数人的最佳解决方案,它很简短且生成噪音较少,即使它不是最常规的方法。话虽如此,人们可能会想知道为什么使用 SQL 生成数字/日期列表如此困难... - Florian Fasmeyer

34

使用这个,

DECLARE @start_date DATETIME = '2015-02-12 00:00:00.000';
DECLARE @end_date DATETIME = '2015-02-13 00:00:00.000';

WITH    AllDays
          AS ( SELECT   @start_date AS [Date], 1 AS [level]
               UNION ALL
               SELECT   DATEADD(DAY, 1, [Date]), [level] + 1
               FROM     AllDays
               WHERE    [Date] < @end_date )
     SELECT [Date], [level]
     FROM   AllDays OPTION (MAXRECURSION 0)

@start_date@end_date作为SP参数传递。

结果:

Date                    level
----------------------- -----------
2015-02-12 00:00:00.000 1
2015-02-13 00:00:00.000 2

(2 row(s) affected)

它完美地运行,但我无法理解它是如何工作的,你有参考链接吗?感谢你的帮助。 - RaRdEvA

20

创建一个存储过程,类似于以下操作:

declare @startDate date;
declare @endDate date;

select @startDate = '20150528';
select @endDate = '20150531';

with dateRange as
(
  select dt = dateadd(dd, 1, @startDate)
  where dateadd(dd, 1, @startDate) < @endDate
  union all
  select dateadd(dd, 1, dt)
  from dateRange
  where dateadd(dd, 1, dt) < @endDate
)
select *
from dateRange

此处提供了演示SQL Fiddle

或者更好的方法是创建一个日历表,然后从中选择。


5
我认为每个数据库都应该有一个日历表。 - Luis LL
2
请考虑使用 option (maxrecursion 32767) - user443854

1

1
你可以创建一个存储过程,传递2个日期。
CREATE PROCEDURE SELECTALLDATES
(
@StartDate as date,
@EndDate as date
)
AS
Declare @Current as date = DATEADD(DD, 1, @BeginDate);

Create table #tmpDates
(displayDate date)

WHILE @Current < @EndDate
BEGIN
insert into #tmpDates
VALUES(@Current);
set @Current = DATEADD(DD, 1, @Current) -- add 1 to current day
END

Select * 
from #tmpDates

drop table #tmpDates

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,