【问题标题】:Generates all dates between two dates stored in a table生成存储在表中的两个日期之间的所有日期
【发布时间】:2016-04-16 19:53:27
【问题描述】:

SQL Server 2014

我需要从表#data 中生成开始日期和结束日期之间的所有日期。表#data 包含几行开始和结束日期。

CREATE TABLE #data  (
    StartDate DATE NOT NULL,
    EndDate DATE NOT NULL,
    Opt INT NOT NULL)

insert into #data values('2016-04-10', '2016-04-12', 2)
insert into #data values('2016-04-10', '2016-04-15', 3)
insert into #data values('2016-05-10', '2016-05-12', 4)

表#data 可能包含数百行。

我的最终选择应包含:

2016-04-10 2
2016-04-11 2
2016-04-12 2
2016-04-10 3
2016-04-11 3
2016-04-12 3
2016-04-13 3
2016-04-14 3
2016-04-15 3
2016-05-10 4
2016-05-11 4
2016-05-12 4

我目前有这个,但我必须扩展#data 中所有行的选择:

DECLARE @StartDateTime DATETIME
DECLARE @EndDateTime DATETIME

SET @StartDateTime = '2015-01-01'
SET @EndDateTime = '2015-01-12';

--delete from #tmp

;WITH DateRange(DateData) AS 
(
    SELECT @StartDateTime as Date
    UNION ALL
    SELECT DATEADD(d,1,DateData)
    FROM DateRange 
    WHERE DateData < @EndDateTime
)
INSERT INTO #tmp SELECT DateData, 1 -- instead of 1 shall be Opt
FROM DateRange
OPTION (MAXRECURSION 0)

select * from #tmp

谢谢。

【问题讨论】:

    标签: sql sql-server date


    【解决方案1】:

    也许这就是你想要的?

    ;WITH DateRange(DateData, EndDate, Opt) AS 
    (
        SELECT StartDate, EndDate , Opt FROM #data
        UNION ALL
        SELECT DATEADD(d,1,DateData), EndDate, Opt
        FROM DateRange 
        WHERE DateData < EndDate
    )
    SELECT DateData, Opt
    FROM DateRange
    ORDER BY opt, DateData
    OPTION (MAXRECURSION 0)
    

    不过,我会考虑生成一个合适的日历表。如果你有一个,你可以更有效地完成你想要的结果(通过使用日历表的连接)。

    有关示例和更多信息,请参阅这些文章:

    http://www.sqlservercentral.com/blogs/dwainsql/2014/03/30/calendar-tables-in-t-sql/

    https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/

    【讨论】:

    • 这个查询是一个更大的查询的一部分,它经常执行并且时间紧迫。我没有日历表,你认为在这种情况下我应该有一个吗?日历表应该是普通/静态表吗?谢谢。
    • @MihaiHangiu 如果您经常执行此类查询和/或使用大型数据集,那么肯定可以。我链接到的文章详细解释了概念和用例。它基本上是一个包含日期和与日期相关的信息的静态表。
    【解决方案2】:

    试试这个

    ;WITH DateRange
    AS 
    (
        SELECT Startdate, Enddate, Opt from #data 
        UNION ALL
        SELECT DATEADD(d,1,Startdate), Enddate, Opt
        FROM DateRange 
        WHERE Startdate < Enddate
    )
    SELECT Startdate, Opt
    FROM DateRange
    Order by Opt
    

    结果

    Startdate   Opt
    ---------------
    2016-04-10  2
    2016-04-11  2
    2016-04-12  2
    2016-04-10  3
    2016-04-11  3
    2016-04-12  3
    2016-04-13  3
    2016-04-14  3
    2016-04-15  3
    2016-05-10  4
    2016-05-11  4
    2016-05-12  4
    

    【讨论】:

      猜你喜欢
      • 2016-01-04
      • 1970-01-01
      • 2012-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 2013-08-09
      相关资源
      最近更新 更多