【问题标题】:Why does DATEDIFF return -1为什么 DATEDIFF 返回 -1
【发布时间】:2019-05-15 14:15:16
【问题描述】:

我试图了解 DATEDIFF 函数在 SQL Server 中的工作原理。以下 T-SQL 返回 -1:

SELECT DATEDIFF(MONTH, 2015-10-25, 2015-12-27)

但是,ending_date 在 start_date 之后,所以我希望得到一个正数,而不是负数。此外,我预计 10 月 25 日和 12 月 27 日之间的差异为 2 个月。相反,SQL Server 返回 -1 个月。有人可以解释发生了什么吗?

【问题讨论】:

  • 提示:这些不是日期。
  • 您需要用引号将它们括起来。第一个值是2015 MINUS 10 MINUS 25,第二个值是2015 MINUS 12 MINUS 27
  • 您确定这些值正确地转换为日期吗?对我来说看起来像整数减法
  • 这是 T-SQL 缺少日期/时间文字的专用语法以及从 INTDATETIME 的隐式转换的完美结合。书籍的陷阱。更好的是,由于DATETIME 使用整天的整数部分,我们有DATEDIFF(DAY, 2015-10-01, 2015-10-05) = -DATEDIFF(DAY, '2015-10-01', '2015-10-05')。不幸的是,可怜的开发人员通过反转符号来“修复”它......

标签: sql-server tsql date


【解决方案1】:

您缺少撇号:

SELECT  2015-10-25 AS First, 
        2015-12-27 AS Second,
        CAST(2015-10-25 As DateTime) AS [First as datetime],
        CAST(2015-12-27 As DateTime) AS [Second as datetime],
        DATEDIFF(MONTH, 2015-10-25, 2015-12-27) AS WrongResult,
        DATEDIFF(MONTH, '2015-10-25', '2015-12-27') AS CorrectResult

结果:

First   Second  First as datetime       Second as datetime      WrongResult CorrectResult
1980    1976    04.06.1905 00:00:00     31.05.1905 00:00:00     -1          2

SQL Server 将 2015-10-25 视为 int - 数学表达式 (1980) 的结果。
datetime 函数中使用int 会导致SQL Server 将int 值隐式转换为DateTime 值。
int 值表示自 '1900-01-01' 以来的天数 - 由于第二个参数导致较小的 int 值,因此您得到一个负数。

正如 Jeroen Mostert 在他的评论中所写 - 书籍的一个陷阱。

【讨论】:

    【解决方案2】:

    你没有引用你的日期,这意味着你的表达式计算为:

    SELECT DATEDIFF(MONTH, 1980, 1976)
    

    隐式转换为日期时间后的结果为:

    SELECT DATEDIFF(MONTH, '1905-06-04 00:00:00.000', '1905-05-31 00:00:00.000')
    

    所以现在开始日期在结束日期之后。

    【讨论】:

    • 要清楚。 1980 作为日期时间是 1905-06-04 .... select convert(Datetime,2015-10-25)
    【解决方案3】:

    因为您使用的是数字(特别是整数),而不是字符串。 2015-10-25 = 1980 转换为日期时为 '1905-06-04'。另一方面2015-12-27 = 1976,作为日期是'1905-05-31'。因为'1905-05-31''1905-06-04' 早一个月,你得到的结果是-1。

    使用文字字符串和yyyyMMdd 日期:

    SELECT DATEDIFF(MONTH, '20151025', '20151227');
    

    【讨论】:

      【解决方案4】:

      将日期值放在单引号内。

      查询

      SELECT DATEDIFF(MONTH, '2015-10-25', '2015-12-27');
      

      此查询返回2 作为输出。

      【讨论】:

        猜你喜欢
        • 2017-07-04
        • 1970-01-01
        • 1970-01-01
        • 2011-08-14
        • 2012-01-25
        • 2012-03-05
        • 2017-06-04
        • 2015-01-25
        • 2023-03-27
        相关资源
        最近更新 更多