【问题标题】:Calculating Month Start/End With A Fixed Last Day Of Month使用固定的最后一天计算月份开始/结束
【发布时间】:2014-01-10 11:18:36
【问题描述】:

我需要循环遍历一个月内的每一天,但将固定数字作为该月的最后一天。

例如如果一个月的最后一天固定为 30, 一月会变成:

月初:2012 年 12 月 31 日上午 12:00 月底:2013 年 1 月 30 日 12:00AM

我已经实施了以下工作,除了 2 月份外,这些都可以正常工作。我似乎无法找到一个解决方案来确保这始终适用于每个月,无论月末日期是什么。 任何建议都非常感谢。

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

【问题讨论】:

    标签: sql datetime sql-server-2012


    【解决方案1】:

    我认为这个查询(它可以进一步简化,但我想展示我的想法)将@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 的选择是任意的,永远不需要更改。1

    然后我们在最终表达式中所做的是计算从 2001 年 1 月到您的 @dt 变量之间已经过去了多少个月。如果我们然后将相同的月数添加到我们的两个“神奇”日期,那么我们最终会得到同一个月的第 N 天作为 @dt 和上个月的第 N 天到 @dt(或最后一天)如果该月少于 N 天,则为任一月)。

    最后,我们将找到的上个月的第 N 天加 1 来调整它 - 这应该是当月的“第一”天。


    1 唯一重要的是选择两个月份,两个月份都有 31 天,并且在日历中是连续的。年份是任意的。

    【讨论】:

    • 哇!谢谢你。就像你所做的那样,当然不是我想走的路线。似乎工作完美。 :-) 非常感谢
    【解决方案2】:

    您的事情有点过于复杂,我认为以下内容可以满足您的要求:

    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”的设置之上,但上面应该是一个好的起点。

    【讨论】:

    • 谢谢。然而,一个月的最后一天并不总是本月的最后一天。例如,有时一个月的最后一天是 25 日,在这种情况下,26 日至 31 日将落入 2 月,而 1 月初将是 12 月 26 日。希望这是有道理的。
    • 可能值得用这些规则的详细信息更新问题。例如SQL 如何知道所需的月份长度?你怎么知道哪些月份的最后一天是 25 号?
    • 它在那里为“DECLARE @monthEndDate INT = 30” 这将为整个操作预设并适用于所有月份。但是,SQL 需要能够在此处接受任何值。可以是 31、30、29、28 等
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 2010-09-18
    相关资源
    最近更新 更多