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

Hun*_*eez -4 sql t-sql sql-server sql-server-2008

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

Select DATEADD(yy,116, 0)
Run Code Online (Sandbox Code Playgroud)

输出:

2016-01-01 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

还有这个

Select DATEADD(yy,116 +1, -1)
Run Code Online (Sandbox Code Playgroud)

退还给我一年中的最后一天?

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

Abd*_*eed 5

日期01900-01-01,

所以日期-11899-12-31IE(减少1天1900-01-01)

SELECT CONVERT(datetime, 0) : Result is 1900-01-01 00:00:00.000
Run Code Online (Sandbox Code Playgroud)

因此Select DATEADD(yy,116 +1, -1)将在1899年增加116 + 1(即117)年

(117 years will add to 1899-12-31 00:00:00.000)


Lie*_*sel 5

这是我的解释。

DATEADD(yy...正在向给定日期添加年份。(顺便说一句,缩写形式是邪恶的,DATEADD(YEAR,...)为了清晰起见,您应该使用缩写形式)。

0正如其他人所说,日期是 1900 年 1 月 1 日星期一午夜。日期-1是 1899 年 12 月 31 日星期日,前一天。

如果添加116+1到 Date,-1则会得到 12 月 31 日,(1899 + 117) = 2016。您还可以SELECT DATEADD(YEAR,117, '1899-12-31')使用日期文字将其写为或多种其他方式。

奖金

至于为什么它返回 aDatetime而不是 a Datetime2、 aSmalldatetime或任何其他类型,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
Run Code Online (Sandbox Code Playgroud)

额外奖励

如果您想要今年的最后一天:

SELECT DATEADD(DAY, -1, DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE())+1,0))
Run Code Online (Sandbox Code Playgroud)

或者,如果您想要当年的最后一个可解析的 datetime2 (即元旦午夜之前 100 纳秒):

SELECT DATEADD(NANOSECOND, -100,CAST(DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE())+1,0) AS DATETIME2(7))) 
Run Code Online (Sandbox Code Playgroud)

检查每一个,希望您能够弄清楚它们在做什么。