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
我正在尝试在 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