以十分之一秒的精度获得日期差异的最佳方法

Best way to get date difference with an accuracy of a tenth of a second

我有一个 table 有两个日期和一个浮点值,它是两个日期的秒数之差(小数点后一位。)

这是我正在使用的:

CREATE TABLE [dbo].[table](
    --timestamp and id
    [start] datetime    NULL,
    [end]   datetime    NULL,
    [dif]   AS          ROUND(datediff(millisecond,[start],[end])/1000.0,1)
)

除了相对较大之外,它似乎不是很有效。做同样的事情有更好的方法吗?喜欢:datediff(secondtenth,[start],[end])/10.0

这不是 SQL 服务器特定的,而是 ANSI SQL,并且被很多 DBMS-s 支持。

首先 - DATETIME 通常不是获取小数秒的数据类型。我将为此使用 TIMESTAMP,默认比例为 6(微秒),与 ANSI 标准相同。

话虽如此,除了 DATEDIFF() 之外,我们还有 TIMESTAMPDIFF()。但是 datepart 可能是 secondmillisecondmicrosecond。真倒霉。

解决方法是将 TIMESTAMPDIFF() 返回的整数除以 100,然后将结果强制转换回整数。现在一些 DBMS 截断为 FLOOR(number)::INTEGER 一个带小数的数字。如果 MS SQL 这样做,只需在硬转换前将 0.5 添加到除以 100 的部分。它在任何情况下都比 ROUND() 快得多。

并且我使用 the_startthe_end 作为列名以避免保留字并保持在 ANSI 标准内。 (自由、平等、便携 ...)

看这里:

WITH foo(the_start,the_end) AS (
          SELECT TIMESTAMP '2017-01-11 07:31:26.016270',TIMESTAMP '2017-01-11 07:31:43.190093'
UNION ALL SELECT TIMESTAMP '2017-01-11 07:31:51.952073',TIMESTAMP '2017-01-11 07:31:52.091006'
UNION ALL SELECT TIMESTAMP '2017-01-11 07:32:10.305528',TIMESTAMP '2017-01-11 07:32:35.460201'
UNION ALL SELECT TIMESTAMP '2017-01-11 07:32:35.460201',TIMESTAMP '2017-01-11 07:32:35.599238'
)
SELECT
  the_start
, the_end
, TIMESTAMPDIFF(millisecond, the_start,the_end) AS diff_ms
, CAST(TIMESTAMPDIFF(millisecond, the_start,the_end)/100 AS INT) AS diff_tenth_sec
FROM foo;
the_start                 |the_end                   |diff_ms|diff_tenth_sec
2017-01-11 07:31:26.016270|2017-01-11 07:31:43.190093| 17,174|           172
2017-01-11 07:31:51.952073|2017-01-11 07:31:52.091006|    139|             1
2017-01-11 07:32:10.305528|2017-01-11 07:32:35.460201| 25,155|           252
2017-01-11 07:32:35.460201|2017-01-11 07:32:35.599238|    139|             1

玩的开心- 理智的马可

这是一个解决一些潜在溢出问题的示例,任何超过大约 23 天的间隔似乎都会给 datediff 带来溢出,但这将持续数十年

declare @start as datetime;
declare @end as datetime;

set @start = '20100701 10:10:10.125';
set @end = '20100702 10:10:10.225';

select round((cast(@end as float) - cast(@start as float)) * 24 * 3600, 1);

+++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++

通过这个测试,我发现性能几乎没有差异,这是针对 1000 万次计算,在我的 PC 上两组都需要 13 秒

declare @start as datetime;
declare @end as datetime;
DECLARE @MS as float;
DECLARE @I as int;


SET @I = 0;

SET @START = getdate();

WHILE @I < 10000000
BEGIN

    SET @MS = round((cast(getdate() as float) - cast(@start as float)) * 24 * 3600, 1);
    SET @I = @I + 1;
END

PRINT @MS;

SET @START = getdate();
SET @I= 0;

WHILE @I < 10000000
BEGIN

    SET @MS = ROUND(datediff(millisecond,@start,getdate())/1000.0,1)
    SET @I = @I + 1;
END

PRINT @MS;