以十分之一秒的精度获得日期差异的最佳方法
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 可能是 second
或 millisecond
或 microsecond
。真倒霉。
解决方法是将 TIMESTAMPDIFF() 返回的整数除以 100,然后将结果强制转换回整数。现在一些 DBMS 截断为 FLOOR(number)::INTEGER 一个带小数的数字。如果 MS SQL 这样做,只需在硬转换前将 0.5 添加到除以 100 的部分。它在任何情况下都比 ROUND() 快得多。
并且我使用 the_start
和 the_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;
我有一个 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 可能是 second
或 millisecond
或 microsecond
。真倒霉。
解决方法是将 TIMESTAMPDIFF() 返回的整数除以 100,然后将结果强制转换回整数。现在一些 DBMS 截断为 FLOOR(number)::INTEGER 一个带小数的数字。如果 MS SQL 这样做,只需在硬转换前将 0.5 添加到除以 100 的部分。它在任何情况下都比 ROUND() 快得多。
并且我使用 the_start
和 the_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;