当负数与MONTH datepart一起使用时,DATEADD问题

时间:2016-04-14 09:11:43

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

来自DATEADD文档:

  

如果datepart是月份,而日期月份的天数多于返回日期   月份和日期日在返回月份中不存在,最后一个月   返回月份的日期。例如,九月有30   天;因此,以下两个陈述将于2006-09-30回归   00:00:00.000:

     

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

     

SELECT DATEADD(month,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 个答案:

答案 0 :(得分:1)

正如其他评论所说,如果上个月的某一天存在,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日。

答案 1 :(得分:0)

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

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

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

据推测,这是因为你不能在一个月内有30天的第31天,它会超过日期字段,但是你可以在一个月内有30个月,31天就可以了。

答案 2 :(得分:0)

日期添加功能的简单工作流程

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

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

output: 2016-02-29 00:00:00.000

在你的例子中

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

总结: 功能用于向前填充和向后填充。