SQL 服务器 - 奇怪的 DateDiff 行为
SQL Sever - Weird DateDiff Behavior
我有以下简单查询
select DATEADD(MONTH, DATEDIFF(MONTH, -32, '2020-02-29')-32, -1)
select DATEADD(MONTH, DATEDIFF(MONTH, -31, '2020-02-29')-31, -1)
由于 -31 和 -32 中的月数不同,我预计每行的输出会有所不同。
这两行 return 2017-07-31 00:00:00.000 我完全不知道为什么!
有人可以给我解释一下吗?
如 documentation 中所述 dateadd()
:
If the following are true:
- datepart is month
- the date month has more days than the return month
- the date day does not exist in the return month
Then, DATEADD returns the last day of the return month.
来自我的评论:
Why would you expect different values? Both DATEDIFF(MONTH, -32, '20200229')-32
and DATEDIFF(MONTH, -31, '20200229')-31
result in the value 1411
. The "date" -1
is 1899-12-31
, and adding 1411
months (117 years 7 months) to that is 2017-07-31
.
让我们分解一下:
SELECT DATEDIFF(MONTH, -32, '20200229')-32 AS DD1, DATEDIFF(MONTH, -31, '20200229')-31 AS DD2;
这个 returns 以下:
DD1 DD2
----------- -----------
1411 1411
我们也可以将上面的步骤分解成更多的步骤。对于 datetime
,日期 0
是 1900-01-01
,每个完整整数表示在该日期上添加那么多天。 -32
作为日期因此是 1899-11-30
,而 -31
是 1899-12-01
。这给了我们以下 2 个表达式:
SELECT DATEDIFF(MONTH, '18991130', '20200229') AS M1, DATEDIFF(MONTH, '18991201', '20200229') AS M2;
这个 returns 以下:
M1 M2
----------- -----------
1443 1442
这是有道理的,因为 DATEDIFF
计算了 2 个日期之间 "ticks" 的次数。所以对于表达式 DATEDIFF(YEAR, '2019-12-31T23:59:59.9999999','2020-01-01T00:00:00.000000')
返回值 1
,即使只过去了 1 毫秒,因为年份的值已经改变(1)。
该表达式的下一部分分别是 1443 - 32
和 1442 - 31
。两者都是 1411
(基础数学)。
然后你就有了 "date" -1
。然后您将 1411
个月(即 117 年零 7 个月)添加到日期 1899-12-31
,这(不出所料)returns 相同的值:2017-07-31
。 1899 + 117 = 2016
。 12 + 7 = 7
因为我们是按月工作,所以把1
转为年份:2017-07-31
。
我有以下简单查询
select DATEADD(MONTH, DATEDIFF(MONTH, -32, '2020-02-29')-32, -1)
select DATEADD(MONTH, DATEDIFF(MONTH, -31, '2020-02-29')-31, -1)
由于 -31 和 -32 中的月数不同,我预计每行的输出会有所不同。
这两行 return 2017-07-31 00:00:00.000 我完全不知道为什么!
有人可以给我解释一下吗?
如 documentation 中所述 dateadd()
:
If the following are true:
- datepart is month
- the date month has more days than the return month
- the date day does not exist in the return month
Then, DATEADD returns the last day of the return month.
来自我的评论:
Why would you expect different values? Both
DATEDIFF(MONTH, -32, '20200229')-32
andDATEDIFF(MONTH, -31, '20200229')-31
result in the value1411
. The "date"-1
is1899-12-31
, and adding1411
months (117 years 7 months) to that is2017-07-31
.
让我们分解一下:
SELECT DATEDIFF(MONTH, -32, '20200229')-32 AS DD1, DATEDIFF(MONTH, -31, '20200229')-31 AS DD2;
这个 returns 以下:
DD1 DD2
----------- -----------
1411 1411
我们也可以将上面的步骤分解成更多的步骤。对于 datetime
,日期 0
是 1900-01-01
,每个完整整数表示在该日期上添加那么多天。 -32
作为日期因此是 1899-11-30
,而 -31
是 1899-12-01
。这给了我们以下 2 个表达式:
SELECT DATEDIFF(MONTH, '18991130', '20200229') AS M1, DATEDIFF(MONTH, '18991201', '20200229') AS M2;
这个 returns 以下:
M1 M2
----------- -----------
1443 1442
这是有道理的,因为 DATEDIFF
计算了 2 个日期之间 "ticks" 的次数。所以对于表达式 DATEDIFF(YEAR, '2019-12-31T23:59:59.9999999','2020-01-01T00:00:00.000000')
返回值 1
,即使只过去了 1 毫秒,因为年份的值已经改变(1)。
该表达式的下一部分分别是 1443 - 32
和 1442 - 31
。两者都是 1411
(基础数学)。
然后你就有了 "date" -1
。然后您将 1411
个月(即 117 年零 7 个月)添加到日期 1899-12-31
,这(不出所料)returns 相同的值:2017-07-31
。 1899 + 117 = 2016
。 12 + 7 = 7
因为我们是按月工作,所以把1
转为年份:2017-07-31
。