获取开始日期和结束日期之间的日期

Posted

技术标签:

【中文标题】获取开始日期和结束日期之间的日期【英文标题】:Get dates between start and end date 【发布时间】:2018-08-21 14:51:04 【问题描述】:

您好,我有一个问题。

我需要能够使用 SQL 查询根据开始和结束日期以月为单位查找日期。 IE。开始日期:2013-08-01 00:00:00.000,结束日期:2015-08-01 00:00:00.000 结果必须如下:

2013-08-01 00:00:00.000,
2013-09-01 00:00:00.000,
2013-10-01 00:00:00.000,
2013-11-01 00:00:00.000,
2013-12-01 00:00:00.000,
2014-01-01 00:00:00.000,
2014-02-01 00:00:00.000,
2014-03-01 00:00:00.000,
2014-04-01 00:00:00.000,
2014-05-01 00:00:00.000,
2014-06-01 00:00:00.000,
2014-07-01 00:00:00.000,
2014-08-01 00:00:00.000,
2014-09-01 00:00:00.000,
2014-10-01 00:00:00.000,
2014-11-01 00:00:00.000,
2014-12-01 00:00:00.000,
2015-01-01 00:00:00.000,
2015-02-01 00:00:00.000,
2015-03-01 00:00:00.000,
2015-04-01 00:00:00.000,
2015-05-01 00:00:00.000,
2015-06-01 00:00:00.000,
2015-07-01 00:00:00.000,
2015-08-01 00:00:00.000

你能帮忙吗? 提前致谢

【问题讨论】:

上述日期与一条记录有关。表格中的每一行都有其开始日期和结束日期。 @scsimon:我认为 OP 在这里提出的问题是:DATE 值是否存在行源...有没有办法在指定范围内生成一组日期值,例如我们可以从中选择的视图。 @spencer7593 抱歉,我删除了重复投票后忘记删除评论。 我会在这里使用一个计数表。 sqlservercentral.com/articles/T-SQL/62867至于具体的实现,我很茫然,因为不清楚你要做什么。 【参考方案1】:

如果是我,我会做一个日历表。当然,你可以用datediff 做很多花哨的 SQL,但它总是看起来很方便,可以加入一个包含 100 年日期的表。如果您要对数据中的日期做很多事情,那么拥有它是一件好事。这样做确实感觉有点“便宜”,但对我来说效果很好。

How to create a Calendar table for 100 years in Sql

然后你可以简单地加入这个,并获取该范围内的日期。

更新

正如@scsimon 指出的那样,链接中接受的答案可能并不理想。不过,请阅读链接,那里有一些制作表格的好主意。

【讨论】:

我不会在这里使用公认的答案......它会很慢。提醒一下【参考方案2】:

Tally 表会很快...

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )

select '20130801'
union all
select dateadd(month,N,'20130801') 
from cteTally
where n <= datediff(month,'20130801','20150801')

更清楚地使用参数

declare @startDate date = '20130801'
declare @endDate date = '20150801'

;WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )

select @startDate
union all
select dateadd(month,N,@startDate) 
from cteTally
where n <= datediff(month,@startDate,@endDate)

【讨论】:

【参考方案3】:

有很多方法可以解决这个问题。我经常使用的是递归 CTE:

DECLARE @StartDate      date = '2013-08-01'
DECLARE @EndDate        date = '2015-08-01'

;WITH
    cte AS
    (
        SELECT      @StartDate      AS CalendarDate
        UNION ALL
        SELECT      DATEADD(MONTH, 1, CalendarDate)
        FROM        cte
        WHERE       CalendarDate < @EndDate
    )

SELECT      CalendarDate
FROM        cte
OPTION      (MAXRECURSION 0)

对于小范围的值(12 个月 x 100 年很小),这非常快。当您需要获得数百万行时,它会变得很慢。根据您手头的问题,您可能需要不同的解决方案。

【讨论】:

仅供参考。使用这样的递归 cte 会导致可怕的性能问题。 sqlservercentral.com/articles/T-SQL/74118 这里的例子是一个小集合,所以没关系。但我更喜欢计数表,超级快。 我非常清楚递归 CTE 的性能问题。根据问题,它可能会或可能不会重要。一个计数表是理想的,但有时您没有权限在数据库中设置一个。 这对于制定该规则的 DBA 来说是可耻的。但幸运的是,您可以像上面的 scsimon 那样使用 ctes 创建一个内联。这种类型的计数表速度非常快,因为它生成零读取以创建数千行。 全面披露,@SeanLange 教我计数表? 非常感谢您对我的帮助,非常感谢

以上是关于获取开始日期和结束日期之间的日期的主要内容,如果未能解决你的问题,请参考以下文章

获取开始日期和结束日期列之间的所有日期[重复]

php 获取开始日期与结束日期之间所有日期

php 获取开始日期与结束日期之间所有日期

php 获取开始日期与结束日期之间所有日期

如何使用 pandas.date_range() 在指定的开始日期和结束日期之间获取具有 n 个指定周期(相等)的时间序列

基于日期获取所有日期 - sql