【问题标题】:SQL Server DateDiff between two dates returns inaccurate values两个日期之间的 SQL Server DateDiff 返回不准确的值
【发布时间】:2017-10-16 01:18:10
【问题描述】:

我正在尝试通过 ETL 作业将字符串转换为 DateTimeOffset(在 SQL Server 中)。基本上,我的字符串看起来像'2017-10-15',我希望将其转换为DatetimeOffset(来自当前的数据库服务器)。

SELECT
    SWITCHOFFSET(DATEADD(mi, DATEDIFF(MI, GETDATE(), GETUTCDATE()), CAST(@DateInString  + ' 00:00:00' AS DATETIMEOFFSET)), DATENAME(tzoffset, SYSDATETIMEOFFSET()))

我在这个语句中遇到了一些奇怪的问题,因为最终输出会比预期的下降 +1 / -1 分钟。至少每 10 条记录/百万会发生这种情况。我试图确定问题,我可以看到问题在于 DATEDIFF() 方法返回 +/-1 分钟。

SELECT DATEDIFF(MI, GETDATE(), GETUTCDATE()) 

这应该完全返回 -600(因为我的数据库服务器 UTC 是 +10)。但是,对于少数记录,它会返回 -599 或 601。我在存储过程中将它们作为单个选择语句执行,并将其作为参数返回。

这很奇怪 SQL 如何在同一个 select 语句中检测到 GETDATE()GETUTCDATE() 的两个不同的日期时间值。

有没有办法强制 SQL 在那些 DATEDIFF 参数中获得完全相同的日期,或者我在这里遗漏了什么?提前致谢

我使用的是 SQL Server 2014 (v12.0)。

存储过程:

CREATE PROCEDURE dbo.SPConvertDateTimeOffset
    @DateInString VARCHAR(10),
    @DateTimeOffset_Value DATETIMEOFFSET OUTPUT,
    @Datediff_Value INT OUTPUT
AS 
BEGIN 
    -- This line returns +/- 1
    SELECT @Datediff_Value = DATEDIFF(MI, GETDATE(), GETUTCDATE())  

    SELECT @DateTimeOffset_Value = SWITCHOFFSET(DATEADD(mi, @Datediff_Value, CAST(@DateInString  + ' 00:00:00' AS DATETIMEOFFSET)), DATENAME(tzoffset, SYSDATETIMEOFFSET()))
END

【问题讨论】:

  • 如果您多次这样做,getdate()getutcdate() 可能会延迟几毫秒。
  • 真的很重要吗?因为,我只得到了 Minutes 部分的 datediff。即使我做了几次,理想情况下它应该让我得到相同的日期时间值。但是,如果我多次执行它,为什么它会以毫秒为单位有差异,您有什么参考吗?
  • 这很重要,因为datediff() 在时间之间测量边界

标签: sql sql-server tsql sql-server-2014 rdbms


【解决方案1】:

@GordonLinoff 解释了为什么会发生这种情况:由于函数的执行时间略有不同,它们可能返回不同的分钟。

要解决此问题,请尝试以下操作:

DECLARE @DateTimeOffset_Value Datetimeoffset
DECLARE @Datediff_Value INT, @DateInString VARCHAR( 10 )
SET @DateInString = CONVERT( VARCHAR, GETDATE(), 112 )
SET @DateTimeOffset_Value = TODATETIMEOFFSET( @DateInString, DATENAME(tzoffset,SYSDATETIMEOFFSET()))
SET @Datediff_Value = DATEDIFF( MI, @DateInString, @DateTimeOffset_Value )
SELECT @DateInString, @DateTimeOffset_Value, @Datediff_Value

它不使用当前日期比较。

注意:在夏令时更改期间,您可能会获得与预期不同的值,具体取决于代码的确切运行时间。

查看https://dba.stackexchange.com/questions/28187/how-can-i-get-the-correct-offset-between-utc-and-local-times-for-a-date-that-is,了解有关如何处理 DTS 更改的更多解决方案。

【讨论】:

  • 我仍在尝试从 MSDN 中找到有关 GetDate() 和 GetUTCDate 在单选下返回不同日期时间的任何参考/链接。但是,这个答案解决了我将日期转换为 datetimeoffset 的问题。谢谢。
  • @Bharathi - 我找不到任何 Microsoft 参考资料,但存在一些关于 SO 处理同一问题的问题:stackoverflow.com/questions/6036223/…stackoverflow.com/questions/3620105/…
【解决方案2】:

这两个函数不是同时执行的。因此,大约 100,000 次中的 1 次(在您的测试中)时间位于分钟边界的两侧。

如果你只想要时区,你可以试试:

选择日期部分(tz, SYSDATETIMEOFFSET())

【讨论】:

    猜你喜欢
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    相关资源
    最近更新 更多