这个代码背后的诀窍是什么



为什么这会给我一个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而不是Datetime2Smalldatetime或任何其他类型,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))) 

仔细检查每一个,希望你能弄清楚他们在做什么。

日期01900-01-01

因此日期-11899-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中日期时间存储的更多信息,您可以阅读本文。

最新更新