这段代码背后的诀窍是什么?

时间:2016-04-05 06:31:37

标签: sql sql-server sql-server-2008 tsql

为什么这会给我一个DATETIME的结果?

Select DATEADD(yy,116, 0)

输出:

2016-01-01 00:00:00.000

和这个

Select DATEADD(yy,116 +1, -1)

一年中的最后一天归还我?

这背后的诀窍是什么?我只是在玩它,但不知道它是怎么来的?

4 个答案:

答案 0 :(得分:5)

日期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

答案 1 :(得分:4)

在这一个上F死马,但这是我的解释。

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被隐式转换(根据正常的转换/转换规则)到日期时间 - 请参阅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))) 

检查每一个,希望你能够解决他们正在做的事情。

答案 2 :(得分:3)

SQL Server日期时间基于1900-01-01以来的天数。

 0 = 1900-01-01
-1 = 1899-12-31

现在你将#116添加116年,然后将#117添加117年。

答案 3 :(得分:0)

Sql server将datetime值存储为8个字节 - 前4个字节表示自1900年1月1日起的天数,最后4个字节表示自午夜以来的刻度数(刻度为3.3毫秒,这就是日期时间准确度的原因)限制是3.3毫秒)。

因此,在将1900-01-01转换为日期时间值时,您会获得1 在转换1900-01-02时,您获得-1
转换1899-12-31时,您会获得def quote(value) return value.inspect unless value.is_a? String if value.include?("'") value.inspect else "'#{value}'" end end

所以,简单的数学 - 增加116年到1900年将给2016年 将在2016-12-31增加117年至1899-12-31。

有关sql server中日期时间存储的更多信息,请阅读this article.