如何从日期列中减去一个月

Jay*_*y C 5 sql sql-server dateadd

我知道 Dateadd 和 datediff,但我找不到如何在实际日期列上使用这些函数的任何信息,而不是像今天使用 SQL Server 的日期。

说我有以下专栏

Dated
06/30/2015
07/31/2015
Run Code Online (Sandbox Code Playgroud)

现在我想添加以下派生列,从 Dated 列中的每一行减去一个月。

Dated             Subtracted
06/30/2015        05/31/2015
07/31/2015        06/30/2015
Run Code Online (Sandbox Code Playgroud)

谢谢

sha*_*t00 6

简短的回答:我怀疑这就是你想要的:

dateadd(day, -datepart(day, Dated), Dated)
Run Code Online (Sandbox Code Playgroud)

However, if you want "regular" subtract one month behavior in tandem with sticking to the end of month, having June 30 fall back to May 31 is slightly trickier. There's a discrepancy between the title or your question and the example where it appears you want the final day of month to stay anchored. It would be helpful for you to clarify this.

dateadd(month, -1, ...) doesn't handle that when the previous month has more days than the starting month although it works the other way around. If that's truly what you need I think this should handle it:

case
    when datediff(month, Dated, dateadd(day, 1, Dated)) = 1
    then dateadd(day, -datepart(day, Dated), Dated)
    else dateadd(month, -1, Dated)
end
Run Code Online (Sandbox Code Playgroud)

There's also a flavor of several date functions in that expression and a sense of how this date stuff can get complicated. The condition in the when looks to see if Dated is the last day of the month by checking that the following day is in a different calendar month. If so we extract the day of month and subtract that many days to jump back to the last day of the previous month. (Months start at one not zero. So for example, counting backward 17 days from the 17th lands in the month before.) Otherwise it uses regular dateadd(month, -1, ...) calculations to jump backward to the same day of month.

Of course if all your dates fall on the end of the month then this simple version will be adequate by itself because it always returns the last day of the previous month (regardless of where it falls in the starting month):

dateadd(day, -datepart(day, Dated), Dated) /* refer back to the top */
dateadd(day, -day(Dated), Dated) /* same thing */
Run Code Online (Sandbox Code Playgroud)

And just for fun and practice with date expressions, another approach is that you could start on a known month with 31 days and calculate relative to that:

dateadd(month, datediff(month, '20151231', Dated) - 1, '20151231')
Run Code Online (Sandbox Code Playgroud)

This finds the number of months between your date and a reference date. It works for all dates since it doesn't matter whether the difference is positive or negative. So then subtracting one from that difference and adding that many months to the reference point is the result you want.

People will come up with some pretty crazy stuff and I'm often amazed (for differing reasons) at some of the variations I see. chancrovsky's answer is a good example for closer examination:

dateadd(month, datediff(month, -1, Dated) - 1, -1)
Run Code Online (Sandbox Code Playgroud)

It relies on the fact that date -1, when treated as implicitly converted to datetime, is the day before January 1, 1900, which does happen to be a month of 31 days as required. (Note that the - 1 in the middle is regular arithmetic and not a date value.) I think most people would advise you to be careful with that one as I'm not sure that it is guaranteed to be portable when Microsoft deprecates features in the future.