如何在 SQL 中显示两个给定日期之间的所有日期
Posted
技术标签:
【中文标题】如何在 SQL 中显示两个给定日期之间的所有日期【英文标题】:How to display all the dates between two given dates in SQL 【发布时间】:2009-09-29 04:28:21 【问题描述】:使用 SQL server 2000。如果开始日期是 06/23/2008
并且结束日期是 06/30/2008
那么我需要查询的输出为
06/23/2008
06/24/2008
06/25/2008
.
.
.
06/30/2008
我创建了一个表名称为整数,它有 1 列,列值为 0、1、2、3、4、5、6、7、8、9 然后我使用了下面提到的查询
尝试查询
SELECT DATEADD(d, H.i * 100 + T .i * 10 + U.i, '" & dtpfrom.Value & "') AS Dates
FROM integers H
CROSS JOIN integers T
CROSS JOIN integers U
order by dates
上述查询仅显示 999 个日期。 999 个日期仅表示 (365 + 365 + 269) 个日期。假设我想选择超过 3 年(01/01/2003 到 01/01/2008)。上面的查询应该不适合。
如何修改我的查询?或者任何其他查询都可用于上述条件。
请向我提供查询。
【问题讨论】:
【参考方案1】:我不会循环创建日期列表,使用数字表(不仅仅是值 0 到 9 的表),它们对很多事情都很有用:http://web.archive.org/web/20150411042510/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-numbers-table.html 使用真正的数字表,你不需要必须多次交叉连接,使查询过于复杂。
要使此方法起作用,您需要进行一次时间表设置:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.columns s1
CROSS JOIN sys.columns s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
设置 Numbers 表后,使用以下查询:
SELECT
@Start+Number-1
FROM Numbers
WHERE Number<=DATEDIFF(day,@Start,@End)+1
捕捉它们:
DECLARE @Start datetime
,@End datetime
DECLARE @AllDates table
(Date datetime)
SELECT @Start = '06/23/2008', @End = '06/30/2008'
INSERT INTO @AllDates
(Date)
SELECT
@Start+Number-1
FROM Numbers
WHERE Number<=DATEDIFF(day,@Start,@End)+1
SELECT * FROM @AllDates
输出:
Date
-----------------------
2008-06-23 00:00:00.000
2008-06-24 00:00:00.000
2008-06-25 00:00:00.000
2008-06-26 00:00:00.000
2008-06-27 00:00:00.000
2008-06-28 00:00:00.000
2008-06-29 00:00:00.000
2008-06-30 00:00:00.000
(8 row(s) affected)
【讨论】:
【参考方案2】:一种可能的方式(不是说它是最好或最有效的)是这样的:
DECLARE @StartDate DATETIME
SET @StartDate = '06/23/2008'
DECLARE @EndDate DATETIME
SET @EndDate = '06/30/2008'
DECLARE @TableOfDates TABLE(DateValue DATETIME)
DECLARE @CurrentDate DATETIME
SET @CurrentDate = @startDate
WHILE @CurrentDate <= @endDate
BEGIN
INSERT INTO @TableOfDates(DateValue) VALUES (@CurrentDate)
SET @CurrentDate = DATEADD(DAY, 1, @CurrentDate)
END
SELECT * FROM @TableOfDates
这适用于任意数量的日期、任意范围的日期,并且不需要具有整数值的特定“帮助”表。
它将所有相关日期存储到内存表变量中,以便您可以将其用于例如另一个 SELECT 语句或任何您需要的语句。
马克
【讨论】:
这是 2005 年前的理想方法,因为您不能使用 CTE - 有关详细信息,请参阅此问题中的 cmets:***.com/questions/1478951/… 这个循环将比使用传统的数字表慢得多,如我的回答中所述。如果这是一次性的,那么可以使用。但是,如果您要生成许多日期范围,请使用更有效的无循环方法。 是的 - 但您不需要额外的数字表!而对于 10 或 20 行,我不知道会有多大差异。 不,小套装不会有太大区别。但是,使用数字表方法,您可以将查询集成到更大的查询中,而使用这种循环方法则不能。如果您必须为一组开始/结束对生成日期范围,则可以使用 Numbers 表。【参考方案3】:见:
Why should I consider using an auxiliary calendar table?
日历表可以做很多事情 更容易围绕任何开发解决方案 涉及日期的商业模式。 最后我检查了一下,这包括 几乎任何商业模式都可以 想一想,在某种程度上。持续的 最终需要的问题 冗长、复杂和低效 方法包括以下 问题:
x 和 y 之间有多少个工作日? ...
【讨论】:
这是一种数据仓库技术,正如你所说的,非常强大。不过,它仍然必须被填充。【参考方案4】:这将使您最多获得 100,000 天:
SELECT DATEADD(d, Y.i * 10000 + X.i * 1000 + H.i * 100 + T .i * 10 + U.i, '" & dtpfrom.Value & "') AS Dates
FROM integers H
CROSS JOIN integers T
CROSS JOIN integers U
CROSS JOIN integers X
CROSS JOIN integers Y
order by dates
【讨论】:
以上是关于如何在 SQL 中显示两个给定日期之间的所有日期的主要内容,如果未能解决你的问题,请参考以下文章