Sql server DATEADD问题(当负数与月份datepart一起使用时)

Sql server DATEADD问题(当负数与月份datepart一起使用时),sql-server,tsql,sql-server-2014,dateadd,Sql Server,Tsql,Sql Server 2014,Dateadd,从文件中: 如果datepart为月,且该月的日期比返回的日期多 返回月份(最后一个)中不存在月份和日期天 返回返回月份的日期。例如,9月有30天 天;因此,以下两条语句返回2006-09-30 00:00:00.000: 选择DATEADDmonth,1,'2006-08-30' 选择DATEADDmonth,1,'2006-08-31' SQL Server知道2016-03的最后一天是31,2016-04的最后一天是30: 那么,为什么会出现以下情况: SELECT DATEADD(MON

从文件中:

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

选择DATEADDmonth,1,'2006-08-30'

选择DATEADDmonth,1,'2006-08-31'

SQL Server知道2016-03的最后一天是31,2016-04的最后一天是30:

那么,为什么会出现以下情况:

SELECT DATEADD(MONTH, -1, '2016-04-30')
SELECT  DATEADD(MONTH, -1, '2016-03-31')
返回2016-03-30 00:00:00.000而不是2016-03-31 00:00:00.000

此外,如果我有以下信息:

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

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

它也不适用于从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天,这很好。

dateadd功能的简单工作流

即。 对于日-它是下一个有效日的添加日 本周-接下来的7天是“添加一周” 对于月份-仅为下个月添加月份,如果日期无效,则向前填写 对于年份-这是添加年份

选择DATEADDMONTH,-1,“2016-03-31”

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

在您的示例中:

2016-03-31-2016-02-31减去1个月,但这不是一个有效日期,因此函数尝试在负数中向后填充\在正数中向前填充。 因此,下一个有效的追溯日期是2016年2月29日

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

如其他注释所述,如果上个月中存在该月的某一天,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号。

答案就在您的问题本身中:……并且返回月中不存在日期…-由于第30天确实存在于3月,它正确地返回了3月30日。如果EOMOUNT函数对您来说不够,并且您希望“坚持使用某种DATEADD方法,您可以使用类似于选择DATEADDMM、DATEDIFFMM、-1、GETDATE、0-1 LastDayOfMonth的方法如果您始终需要当月的最后一天,始终以一个月的31号为起点。就这么简单。或者,计算下一个月的第一天,并使用它,您正在寻找从开始日期算起的一个月内的日期,因此2016-09-30的月份是2016-10-30。DATEADD的设计目的不是为您提供月末值。碰巧,日期20xx-08-30和20xx-08-31从现在起的月份计算与日期20xx-09-30相同。