有没有办法在SQL中计算上个月/上年的昨天/今天?

xam*_*mir 3 sql-server-2008 sql-server datetime date

有没有办法在 SQL 中计算上个月(和去年)的今天(和昨天)?

假设今天是 26-May-2015 那么如何找到?

  • 去年的今天,即 26-May-2014?
  • 上个月的今天,即 26-April-2015?
  • 去年的昨天,即 25-May-2014?
  • 上个月的昨天,即 25-April-2015?

Aar*_*and 10

不应该真的需要任何技巧来处理闰年,但这取决于您期望的结果。通常,您只需先减去较大的部分,因此减去一天之前减去一个月,而不是相反。

这些是否会产生您意想不到的结果?如果是这样,哪些对您来说是“错误的”,为什么?

DECLARE @d TABLE(d DATE);

INSERT @d(d) VALUES('20150330'),('20150331'),
      ('20150430'),('20150531'),('20150526'),

      ('20160229'), -- Leap day: test "Today of last year" and "Yesterday of last year"

      -- Month after leap day: test "Today of last month" and "Yesterday of last month"
      ('20160329'),('20160330'),('20160331'),

      -- March 1st in possible leap year: test "Yesterday"
      ('20160301'), -- test regular leap year
      ('20000301'), -- test century divisible by 400
      ('19000301'), -- test century not divisible by 400 (not a leap year)

      -- March 1st in year AFTER possible leap year: test "Yesterday of last year"
      ('20170301'), -- test regular leap year
      ('20010301'), -- test century divisible by 400
      ('19010301'); -- test century not divisible by 400 (not a leap year)

SELECT

  [Today] = d,
  [Today of last year] = DATEADD(YEAR, -1, d),
  [Today of last month] = DATEADD(MONTH, -1, d),

  [Yesterday] = DATEADD(DAY, -1, d),
  [Yesterday of last year]  = DATEADD(DAY, -1, DATEADD(YEAR, -1, d)),
  [Yesterday of last month] = DATEADD(DAY, -1, DATEADD(MONTH, -1, d)) 

FROM @d;
Run Code Online (Sandbox Code Playgroud)

如果您想以不同的方式处理闰年、假期、周末等,您也可以考虑使用日历表。您真正需要做的是完全理解并解释您的要求。许多月份有 31 天,尤其是闰年,“今天或昨天,上个月或去年”的每种可能组合都可以有多种解释。

  • 缺少一些闰年测试,表明它们得到了正确处理。我希望我可以编辑答案以向他们展示,但我想不出如何在评论中添加任何信息来正确解释它。但看起来确实不需要黑客,所以+1。 (2认同)

Tho*_*erg 7

昨天:

SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE() - 1), 0)
Run Code Online (Sandbox Code Playgroud)

去年的今天:

SELECT DATEADD(YEAR, -1, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0))
Run Code Online (Sandbox Code Playgroud)

上个月的今天:

SELECT DATEADD(MONTH, -1, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0))
Run Code Online (Sandbox Code Playgroud)

去年的昨天:

SELECT DATEADD(YEAR, -1, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE() - 1), 0))
Run Code Online (Sandbox Code Playgroud)

上个月的昨天:

SELECT DATEADD(MONTH, -1, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE() - 1), 0))
Run Code Online (Sandbox Code Playgroud)

奇数日期(特别是闰年)的额外破解:

(如果上一年的日期不存在,请使用之前的日期)

  DECLARE @date DATETIME = '2016-03-1'

  SELECT CASE WHEN DATEADD(YEAR, -1, DATEADD(DAY, DATEDIFF(DAY, 0, @date - 1), 0)) = DATEADD(YEAR, -1, DATEADD(DAY, DATEDIFF(DAY, 0, @date), 0))
         THEN DATEADD(YEAR, -1, DATEADD(DAY, DATEDIFF(DAY, 0, @date - 2), 0))
         ELSE DATEADD(YEAR, -1, DATEADD(DAY, DATEDIFF(DAY, 0, @date - 1), 0))
         END
Run Code Online (Sandbox Code Playgroud)

  • 你想怎么处理?:) (2认同)
  • @Thomas 您是否尝试过我评论中的代码?在这两种情况下它都没有产生 2015-02-28 吗? (2认同)
  • ([另外,请非常小心像`datetime - integer`这样的速记](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/09/20/bad-habits-to-kick-using-shorthand- with-date-time-operations.aspx)) (2认同)