为什么这会给我一个DATETIME的结果?
Select DATEADD(yy,116, 0)
输出:
2016-01-01 00:00:00.000
和这个
Select DATEADD(yy,116 +1, -1)
还我一年中的最后一天吗?
这背后的把戏是什么?我只是在玩它,但不明白它是怎么来的?
在这匹马上鞭打一匹死马,但这是我的解释。
DATEADD(yy...
在给定日期的基础上增加年份。(顺便说一句,缩写形式是邪恶的,为了清楚起见,应该使用DATEADD(YEAR,...)
)。
正如其他人所说,0
的日期是1900年1月1日星期一午夜。日期-1
是1899年12月31日星期日,也就是前一天。
如果将116+1
添加到日期-1
,则得到12月31日,(1899+117)=2016。您也可以将其写成SELECT DATEADD(YEAR,117, '1899-12-31')
或使用日期文字的许多其他方式。
奖金
至于为什么返回Datetime
而不是Datetime2
、Smalldatetime
或任何其他类型,DATEADD
返回您作为日期参数传递的任何类型。-1
隐式转换(根据正常的强制转换/转换规则)为Datetime-请参阅https://msdn.microsoft.com/en-AU/library/ms187928.aspx.
如果你想看到这一点,这段代码将向你展示给DATEADD
不同类型的结果:
SELECT
SQL_VARIANT_PROPERTY(GETDATE(), 'BaseType') BaseType,
SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, GETDATE()), 'BaseType') DateAddBaseType,
SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, CAST(GETDATE() AS DATETIME2)), 'BaseType') DateAddDatetime2,
SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, CAST(GETDATE() AS SMALLDATETIME)), 'BaseType') DateAddSmallDatetime,
SQL_VARIANT_PROPERTY(DATEADD(DAY, 1, CONVERT(DATETIME2, GETDATE() )), 'BaseType') DateAddDatetime2Convert
额外奖金
如果你想要今年的最后一天:
SELECT DATEADD(DAY, -1, DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE())+1,0))
或者,如果您想要当前年份的最后一个可解析日期时间2(即元旦午夜前100ns):
SELECT DATEADD(NANOSECOND, -100,CAST(DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE())+1,0) AS DATETIME2(7)))
仔细检查每一个,希望你能弄清楚他们在做什么。
0
是1900-01-01
,
因此日期-1
为1899-12-31
,即(从1900-01-01
减少1天)
SELECT CONVERT(datetime, 0) : Result is 1900-01-01 00:00:00.000
因此Select DATEADD(yy,116 +1, -1)
将为1899 增加116+1(即117)年
(117 years will add to 1899-12-31 00:00:00.000
)
SQL Server日期时间基于1900-01-01
之后的天数。
0 = 1900-01-01
-1 = 1899-12-31
现在,你把116年加在#1上,把117年加在#2上。
Sql服务器将日期时间值存储为8个字节-前4个字节表示自1900年1月1日起的天数,后4个字节代表自午夜以来的刻度数(刻度为3.3毫秒,这就是日期时间精度限制为3.3毫秒的原因)。
因此,当将0
转换为datetime值时,将得到1900-01-01
转换1
时,会得到1900-01-02
,
转换CCD_ 26时得到CCD_。
所以,简单的数学计算-将116年加上1900年,就可以得到2016年。
在1899-12-31年的基础上再增加117年将导致2016-12-31年。
有关sql server中日期时间存储的更多信息,您可以阅读本文。