列出两个日期范围之间的日期

时间:2014-11-25 17:54:13

标签: sql-server-2008 datetime while-loop

我的表1有3列id,startdate和enddate。如果订单ID是主键,如何列出日期范围Startdate和Enddate之间的日期?

我有什么:

id     Startdate     EndDate
1      2/11/2014     2/13/2014
2      2/15/2014     2/17/2014

我需要什么:

id       Date
1      2/11/2014
1      2/12/2014
1      2/13/2014
2      2/15/2014
2      2/16/2014
2      2/17/2014

我该怎么做?

3 个答案:

答案 0 :(得分:2)

使用递归CTE:

WITH tmp AS (
    SELECT  id, StartDate AS [Date], EndDate
    FROM    MyTable
    UNION ALL
    SELECT  tmp.id, DATEADD(DAY,1,tmp.[Date]), tmp.EndDate
    FROM    tmp
    WHERE   tmp.[Date] < tmp.EndDate
)

SELECT tmp.ID, tmp.[Date]
FROM tmp
ORDER BY tmp.id, tmp.[Date]
OPTION (MAXRECURSION 0) -- For long intervals

如果你必须使用游标/循环,大多数时候你做错了。

答案 1 :(得分:0)

如果您按Why should I consider using an auxiliary calendar table?所示进行辅助日历表的一次性设置,如果您不需要它们,可能会省略很多列,如下所示:

CREATE TABLE dbo.Calendar  
(  
    dt SMALLDATETIME NOT NULL 
        PRIMARY KEY CLUSTERED,  

    Y SMALLINT,  
    M TINYINT,  
    D TINYINT
 ) 
GO

SET NOCOUNT ON 
DECLARE @dt SMALLDATETIME 
SET @dt = '20000101' 
WHILE @dt < '20300101' 
BEGIN 
    INSERT dbo.Calendar(dt) SELECT @dt 
    SET @dt = @dt + 1 
END;

UPDATE dbo.Calendar SET 
    Y = YEAR(dt),  
    M = MONTH(dt),  
    D = DAY(dt);

(根本不需要Y,M,D列,但我留下了这些列以显示可以存储更多数据以便快速访问 - 我链接的文章显示了如何使用它。)< / p>

然后,如果您的表名为“so”,那么您的代码将只是

SELECT A.id, C.dt
FROM so AS A
JOIN Calendar AS C
ON C.dt >= A.StartDate AND C.dt<= A.EndDate

使用这样的辅助表的一个好处是您的查询可以更快:在设置一个时完成的工作是一次性成本,这在使用期间不会发生..

答案 2 :(得分:0)

可以使用下面的查询来获取两个日期范围之间的日期列表,而不是使用CTE(在日期范围很大时过度递归和执行)。

  

DECLARE @StartDateSTR AS VARCHAR(32); DECLARE @EndDateSTR AS   VARCHAR(32); DECLARE @EndDate AS DATE; DECLARE @StartDate AS DATE;

     

SET @StartDateSTR = '01 / 01/1990'; SET @EndDateSTR = '03 / 31/2025';组   @StartDate = CAST(@StartDateSTR AS date); SET @EndDate =   cast(@EndDateSTR AS date);选择       DATEADD(DAY,n1.rn - 1,@ StartDate)AS dt FROM(SELECT rn = Row_number()OVER(ORDER BY(SELECT NULL))FROM sys.objects a   CROSS JOIN sys.objects b CROSS JOIN sys.objects c CROSS JOIN   sys.objects d)as n1 WHERE n1。[rn]&lt; = Datediff(dd,@ StartDate,   @EndDate)+1;