SQL Server 中的日期数学是如何工作的?

Eri*_*ing 7 sql-server date-math

我经常在子句中看到用DATEADD和编写的查询来定义一个范围,将日期时间展平为 0 小时,或者找到一个月或一年的最后一天,但我不明白所有部分是如何工作的。DATEDIFFWHERE

例如,这将查找从当天开始到 30 天前一天开始的日期。

SELECT *
FROM tbl
WHERE datecol >= DATEADD(DAY, DATEDIFF(DAY, 0, GETUTCDATE()), 0)
AND datecol   <  DATEADD(DAY, DATEDIFF(DAY, 0, GETUTCDATE()), -30);
Run Code Online (Sandbox Code Playgroud)

这的所有不同部分都完成了什么?

Eri*_*ing 11

了解日期数学如何工作的最好方法是将查询分解为各个部分。

从这个开始:

SELECT GETUTCDATE() AS utc_date
Run Code Online (Sandbox Code Playgroud)

在这个特定的日子,它返回2017-10-04 19:34:20.050

在日期数学中,数字 0 和日期 1900-01-01 可以互换。

   SELECT DATEDIFF(DAY, 0, GETUTCDATE()) AS [what does zero mean?],
          DATEDIFF(DAY, '19000101', GETUTCDATE()) AS [it means 1900-01-01]
Run Code Online (Sandbox Code Playgroud)

这意味着您几乎可以将任何数字转换为日期。甚至负数。

   SELECT CONVERT(DATETIME, -1) AS [how is -1 a date?]
Run Code Online (Sandbox Code Playgroud)

这将带回1899-12-31 00:00:00.000,这与此相同:

SELECT DATEADD(DAY, -1, '19000101') AS [zero minus 1 days]
Run Code Online (Sandbox Code Playgroud)

只需从 1900-01-01 减去一天。很奇怪吧?

这对我们有什么帮助?

让我们看看我们的原始查询:

SELECT DATEDIFF(DAY, 0, GETUTCDATE())
Run Code Online (Sandbox Code Playgroud)

这为我们提供了1900-01-01与当前日期之间的天数。这意味着完整的表达:

SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETUTCDATE()), 0)
Run Code Online (Sandbox Code Playgroud)

是将1900-01-01和 当前之间的天数添加到1900-01-01. 这为我们提供了当天的开始,即 0 小时。

第二部分做同样的事情,除了从1900-01-010 小时减去 30 天。

DATEADD(DAY, DATEDIFF(DAY, 0, GETUTCDATE()), -30);
Run Code Online (Sandbox Code Playgroud)

如果这太难记了,我完全理解。

有关重要日期计算的备忘单,请参阅Tim Ford 的文章

有关重要日期的日历表,请参阅Aaron Bertrand 的文章