SQL 存储过程:从开始日期到结束日期增加月份

SQL stored procedure: increment months from a starting date to an end date

我正在尝试在 SQL 服务器中创建一个存储过程,它基本上会增加从给定开始日期到给定结束日期的月份,并将它们更新为预定义的 table。

问题: 有点像这样:

Exec MonthRunner @Start ='2014-01-01', @End = '2014-06-01'

应该给我这样的 table:

Date 
2014-01-01
2014-02-01
2015-03-01
2015-04-01
2015-05-01
2015-06-01

方法: 使用光标编程的循环。类似于此:

Create Procedure MonthRunner(@Start date, @End date)
AS
DECLARE @Date date
DECLARE @getid CURSOR


SET @getid = CURSOR FOR
Select (@Start)


Set @getid 
OPEN @getid 
FETCH NEXT
FROM @getid into @Date


WHILE @@FETCH_STATUS = 0
BEGIN
SET @Date = (Select Dateadd(Month, 1, @Date))
DECLARE @sqlrun varchar(max)

SET @sqlrun= 'Update myTable' + 'Set Date=' + @Date
EXEC @sqlrun


fetch next 
from @getid into @Date
END

CLOSE @getid
DEALLOCATE @getid

到目前为止我的结果是:

Update myTable Set Date='2014-02-01'

但是没有循环,我也不知道如何使用变量@End 终止循环。

非常感谢您的帮助! 提前致谢,

克莱门斯

这可以通过递归 CTE 轻松完成:

;WITH cte AS (
    SELECT      @Start      AS [Month]
    UNION ALL
    SELECT      DATEADD(MONTH, 1, [Month])
    FROM        cte
    WHERE       [Month] < @End
)

SELECT  [Month]
FROM    cte
OPTION  (MAXRECURSION 0)

这是一个 table 值的函数,用于获取月初:

CREATE FUNCTION dbo.MonthBegin (   
    @date DATE = NULL
  , @offset INT = 0
)
RETURNS TABLE   
AS   
RETURN (
    SELECT D = DATEADD(m, DATEDIFF(m, 0, @date) + @offset, 0)
);

单独来看,此功能并不能完全满足您的需要。将它与一组整数结合起来,你会得到很多乐趣:

DECLARE @seedDate DATE = GETDATE();

SELECT *
FROM dbo.RangeInt(-100, 100) Nums
CROSS APPLY dbo.MonthBegin(@seedDate, Nums.N) Dates;

以上示例使用 TVF 生成一组介于 -100 和 100 之间的数字,然后将这些数字传递给 MonthBegin TVF(连同种子日期)。您也可以将此写成基于数字 table 或 CTE...任何对您来说最 familiar/comfortable 的东西。

我循环了类似这样的:

DECLARE @Start date
DECLARE @End date 
DECLARE @counter date

set @counter = @Start
    while @counter <= @End
    begin
          print 'The counter is ' + cast(@counter as char)
         set @counter = (Select Dateadd(Month, 1, @counter))
    end

您如何看待这个解决方案? (当然我要改文)

在 sp

中从开始日期到结束日期递增月份
ALTER PROCEDURE "dbo"."monthIncrementSp"
AS
    DECLARE @startDate VARCHAR(50);
    DECLARE @endDate VARCHAR(50);

    SET @startDate = '01-01-2017';
    SET @endDate = '31-12-2017';

    SELECT TOP (DATEDIFF(MONTH, CONVERT(DATE, @startDate, 105),CONVERT(DATE, @endDate, 105))+1)
    DATEADD(MONTH, ROW_NUMBER() OVER (ORDER BY name)-1, CONVERT(DATE, @startDate, 105))
    FROM sys.all_columns