在日期范围之间生成日期

Nat*_*Pet 35 sql t-sql sql-server range sql-server-2008

我需要填充一个表,该表将存储2个给定日期之间的日期范围:09/01/11 - 10/10/11

所以在这种情况下,表格将从09年1月1日开始并存储每天直到它到达10/10/11我想知道在SQL Server中是否有一种灵活的方式 - 我目前正在使用SQL Server 2008 . 谢谢

Stu*_*rth 39

易于SQL 2005+; 如果你有一个数字或计数表更容易.我在下面假装:

DECLARE @StartDate DATE = '20110901'
  , @EndDate DATE = '20111001'

SELECT  DATEADD(DAY, nbr - 1, @StartDate)
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
          FROM      sys.columns c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)
Run Code Online (Sandbox Code Playgroud)

如果您有一个计数表,请将子查询替换为表.没有递归.


Abe*_*ler 37

如果您使用的是SQL Server 2005或更高版本,请尝试此操作:

WITH Dates AS (
        SELECT
         [Date] = CONVERT(DATETIME,'09/01/2011')
        UNION ALL SELECT
         [Date] = DATEADD(DAY, 1, [Date])
        FROM
         Dates
        WHERE
         Date < '10/10/2011'
) SELECT
 [Date]
FROM
 Dates
 OPTION (MAXRECURSION 45)
Run Code Online (Sandbox Code Playgroud)

一个很好的例子,你可以用CTE做很酷的事情.

  • +1我提到我喜欢递归吗?http://stackoverflow.com/users/570191/adrian (9认同)
  • 喜欢一个好的递归笑话.好先生,先生. (3认同)

sll*_*sll 11

- 声明

DECLARE @dates TABLE(dt datetime)    
DECLARE @dateFrom datetime
DECLARE @dateTo datetime

SET @dateFrom = '2001/01/01'
SET @dateTo = '2001/01/12'
Run Code Online (Sandbox Code Playgroud)

- 查询:

WHILE(@dateFrom < @dateTo)
BEGIN
   SELECT @dateFrom = DATEADD(day, 1,@dateFrom)
   INSERT INTO @dates 
   SELECT @dateFrom
END
Run Code Online (Sandbox Code Playgroud)

- 输出

SELECT * FROM @dates
Run Code Online (Sandbox Code Playgroud)

  • @AbeMiessler - 公平地说,递归CTE仍然是一个循环. (12认同)
  • 循环很严重 (3认同)

小智 10

这里有一个不需要递归的解决方案,同时这个表值函数可以在很多查询中重用,不需要再次重复声明样板变量。对于那些不想递归的人来说,这是唯一的选择。

创建这个简单的函数:

CREATE FUNCTION [dbo].[GenerateDateRange]
(@StartDate AS DATE,
 @EndDate AS   DATE,
 @Interval AS  INT
)
RETURNS @Dates TABLE(DateValue DATE)
AS
BEGIN
    DECLARE @CUR_DATE DATE
    SET @CUR_DATE = @StartDate
    WHILE @CUR_DATE <= @EndDate BEGIN
        INSERT INTO @Dates VALUES(@CUR_DATE)
        SET @CUR_DATE = DATEADD(DAY, @Interval, @CUR_DATE)
    END
    RETURN;
END;
Run Code Online (Sandbox Code Playgroud)

然后选择:

select *
from dbo.GenerateDateRange('2017-01-03', '2017-12-01', 1)
Run Code Online (Sandbox Code Playgroud)


SQL*_* RV 5

我意识到这是一个旧线程,但我不得不承认我对这里给出的过多的递归和循环解决方案感到沮丧。我想知道有多少人意识到递归只不过是一个非常昂贵的循环?我理解创建表值函数的愿望,但我建议以下更有效,因为它是基于集合的,没有循环、递归或重复的单个插入语句:

CREATE FUNCTION dbo.GenerateDateRange(@StartDate AS DATE, @EndDate AS DATE)
RETURNS TABLE WITH SCHEMABINDING AS
    WITH e1(n) AS (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS x(n)) -- 16 records
        ,e2(n) AS (SELECT 1 FROM e1 a CROSS JOIN e1 b) -- 16^2 or 256 records (16*16)
        ,cteTally(n) AS (SELECT ROW_NUMBER() over (ORDER BY 1) AS n FROM e2 a CROSS JOIN e2 b) -- 16^4 or 65,536 records (256*256)
    SELECT DATEADD(DAY, n-1, @StartDate)
    FROM cteTally
    WHERE n <= DATEDIFF(DAY, @StartDate, @EndDate) + 1;
GO
Run Code Online (Sandbox Code Playgroud)