2014-01-10 75 views
0

我需要循环一个月内的每一天,但固定的数字作为月份的最后一天。计算月份开始/结束时固定的月份最后一天

E.g.如果该月的最后一天被固定为30, 月将成为:

开始每月:2012年12月31日12:00 AM 月结束:2013年1月30日上午12:00

我已经实现了除了二月份之外,其他的工作都很完美。我似乎无法找到一个解决方案,无论月结束日期是多少,都能确保每个月都能正常工作。 任何建议,非常感谢。

DECLARE @dt DATETIME 
DECLARE @DayInstance DATETIME 
DECLARE @LastDayOfMonth DATETIME 
DECLARE @monthEndDate INT = 30 


SET @dt = '2012-01-01 00:00:00.000' 


WHILE @dt < GETDATE() 
BEGIN 
    SET @DayInstance = @dt 
    SET @LastDayOfMonth = (SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,@dt))),DATEADD(mm,1,@dt)),101)) 

    IF @monthEndDate > 0 
     BEGIN 
      SET @LastDayOfMonth = DATEADD(DAY,(@monthEndDate-DATEPART(dd,@LastDayOfMonth)),@LastDayOfMonth) 
      SET @DayInstance = DATEADD(MONTH, -1, @LastDayOfMonth) 
      SET @DayInstance = DATEADD(DAY, 1, @DayInstance) 
     END 
    PRINT 'Month Start Date: ' + CAST(@DayInstance AS NVARCHAR(20)) 
    PRINT 'Month End Date: ' + CAST(@LastDayOfMonth AS NVARCHAR(20))   
    PRINT ''  

    WHILE @DayInstance <= @LastDayOfMonth 
    BEGIN 
     -- Going to do more stuff here 
     SET @DayInstance = DATEADD(DAY, 1, @DayInstance) 
    END 

    SET @dt = DATEADD(MONTH, 1, @dt)  
END 

回答

2

我认为,这个查询(可以进一步简化,但我想告诉我是怎么想)设置@StartDate@EndDate到合适的日期 - 那么你可以做这两个值之间的迭代:

DECLARE @dt DATETIME 
DECLARE @DayInstance DATETIME 
DECLARE @monthEndDate INT = 30 

SET @dt = '2012-01-01 00:00:00.000' 

DECLARE @MagicDate1 DATETIME 
DECLARE @MagicDate2 DATETIME 

SELECT @MagicDate1 = DATEADD(day,@monthEndDate-1,'20010101'), 
     @MagicDate2 = DATEADD(day,@monthEndDate-1,'20001201') 

DECLARE @StartDate DATETIME 
DECLARE @EndDate DATETIME 

SELECT @StartDate = DATEADD(day,1,DATEADD(month,DATEDIFF(month,'20010101',@dt), 
          @MagicDate2)), 
     @EndDate = DATEADD(month,DATEDIFF(month,'20010101',@dt),@MagicDate1) 

select @StartDate,@EndDate 

我首先构造了两个“魔术”日期。分别是2001年1月的第N天和2000年12月的第N天,其中N是期望的月结束日期。请注意,2000/2001的选择是任意的,并且永远不需要改变。

我们则在最后的表达式要做的就是工作了多少个月2001年1月和你@dt变量之间经过。如果我们在两个“魔术”日期中添加相同的月份数,那么我们最终将在同一月份的第N天以@dt和前一个月的第N天为结束日期以@dt(或者如果月份少于N天)。

最后,我们通过加上1来调整我们发现的上个月的第N天 - 这应该是当前月份的“第一天”。


唯一重要的是要选择两个个月当中都有31天的日历中的连续。这一年是任意的。

+0

哇!谢谢你。就像你所做的那样,当然不是我想要的路线。似乎完美地工作。 :-) 非常感谢 – JIbber4568

0

你已经稍微过分复杂的事情,我想我相信你想要做它做的事情如下:

DECLARE @dt DATETIME 
DECLARE @LastDayOfMonth DATETIME 


SET @dt = '2012-01-01 00:00:00.000' 
WHILE @dt < GETDATE() 
BEGIN 
    SET @LastDayOfMonth = DATEADD(DAY,-1,(DATEADD(MONTH,1,@dt))) 
    PRINT 'Month Start Date: ' + CAST(@dt AS NVARCHAR(20)) 
    PRINT 'Month End Date: ' + CAST(@LastDayOfMonth AS NVARCHAR(20))   
    PRINT '' 
    SET @dt = DATEADD(MONTH, 1, @dt)  
END 

这将工作,只要@dt是当月的第一天,否则你将不得不创建一个新的@FirstDayOfMonth变量,并将其设置在`@LastDayOfMonth'的设置上面,但上面应该是一个很好的起点。

+0

谢谢你。然而,本月的最后一天并不总是实际的最后一天。例如,有时候这个月的最后一天将是25号,在这种情况下,26号到31号将进入2月,1月开始将是12月26号。希望这是有道理的。 – JIbber4568

+0

可能值得用这些规则的细节更新问题。例如SQL如何知道所需的月份长度?你怎么知道哪个月的最后一天是25号? – talegna

+0

它以“DECLARE @monthEndDate INT = 30”的形式出现在这里,它将针对整个操作进行预设,并将适用于所有月份。但是SQL需要能够在这里接受任何值。它可能是31,30,29,28等 – JIbber4568