【问题标题】:DATEADD issue when negative number is used with MONTH datepart将负数与 MONTH datepart 一起使用时的 DATEADD 问题
【发布时间】:2016-08-05 17:44:39
【问题描述】:

来自DATEADD 文档:

如果 datepart 是月份并且日期月份的天数比返回的天数多 返回月份中不存在月份和日期日期,最后一个 返回返回月份的日期。例如,九月有 30 天;因此,以下两个语句返回 2006-09-30 00:00:00.000:

SELECT DATEADD(月, 1, '2006-08-30');

SELECT DATEADD(月, 1, '2006-08-31');

SQL Server 知道2016-03 的最后一天是312016-04 的最后一天是30

SELECT DAY(EOMONTH('2016-03-01')) -- 31
SELECT DAY(EOMONTH('2016-04-01')) -- 30

那么为什么会这样:

SELECT DATEADD(MONTH, -1, '2016-04-30')

返回2016-03-30 00:00:00.000 而不是2016-03-31 00:00:00.000

另外,如果我有以下情况:

SELECT  DATEADD(MONTH, -1, '2016-03-31')

它正确返回2016-02-29 00:00:00.000

【问题讨论】:

  • 答案就在你的问题本身:)
  • ..."并且返回月份中不存在日期日期"... - 由于 3 月确实存在第 30 天,因此它正确返回了 3 月 30 日
  • 如果 EOMONTH 功能对您来说还不够,并且您想'坚持某种 DATEADD 类型的方法,您可以使用类似 SELECT DATEADD(MM, DATEDIFF(MM, -1, GETDATE()), 0) - 1 LastDayOfMonth
  • 如果您总是需要一个月的最后一天,请始终以 a 月的 31 日为起点。就这么简单。 (或者,计算下个月的第一天,并使用< 而不是<=

标签: sql-server tsql sql-server-2014 dateadd


【解决方案1】:

它也不适用于从 30 -> 31 的正数,例如:

SELECT DATEADD(MONTH, 1, '2016-09-30')

产生2016-10-30 00:00:00.000 而不是2016-10-31 00:00:00.000

这大概是因为你不能在一个月中的第 31 天有 30 天,它会溢出日期字段,但是你可以在一个月的第 30 天有 31 天就好了。

【讨论】:

  • 它有效,您正在寻找从开始日期起一个月内的日期,因此 2016-09-30 的月份是 2016-10-30。 DATEADD 并非旨在为您提供月末值。碰巧从现在开始计算日期 20xx-08-30 和 20xx-08-31 的月份是相同的日期 20xx-09-30。
【解决方案2】:

dateadd 函数的简单工作流程

即。 对于 Day - 它是添加日期(下一个有效日期) 一周 - 增加一周(接下来的 7 天) 对于月份 - 它是添加月份(仅下个月,如果日期无效则向前填写) 年份 - 添加年份

SELECT DATEADD(MONTH, -1, '2016-03-31')

输出: 2016-02-29 00:00:00.000

在你的例子中:

2016-03-31 -- 2016-02-31(减去 1 个月)但这不是一个有效的日期,所以函数会尝试向后填充(负数)\向前填充日期(正数)。 所以下一个有效的向后日期是 2016-02-29。

结论: 函数用于向前填充和向后填充。

【讨论】:

    【解决方案3】:

    正如其他 cmets 所说,如果上个月存在该月的某天,DATEADD 将使用它,而不是假设您想要“该月的最后一天”。

    如果您确实想要“本月的最后一天”,则必须增加一些逻辑,例如:

    DECLARE @date DATETIME = '30 April 2016'
    SELECT CASE WHEN DATEDIFF(MONTH, @date, DATEADD(DAY, 1, @date)) = 1 THEN     DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, @date), 0))
            ELSE DATEADD(MONTH, -1, @date)
       END
    

    这将假设如果它是一个月的最后一天,您想要上个月的最后一天,而不是明确的 28 日、29 日或 30 日。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 2016-11-10
      • 2020-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多