我试图以秒为单位提取两个SQL DateTime值之间的差异,并使用小数位进行某些性能监视。
我有一个表,“Pagelog”,它有一个“创建”和“结束”日期时间。在过去,我能够做到以下几点:
SELECT DATEDIFF(ms, pagelog_created, pagelog_end)/1000.00 as pl_duration FROM pagelog
但是我开始收到以下错误:
Msg 535, Level 16, State 0, Line 1
The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.
我已经看到很多对这个错误的回应,说明我应该使用一个不太精确的测量单位。但是当我需要区分2.1秒和2.9秒时,这几乎没有帮助,因为DATEDIFF(s,..,..)将返回INT结果并失去我需要的准确性。
我原本以为这是由于我的表格中的一些值具有很大的范围而是运行这个:
SELECT DATEDIFF(s, pagelog_created, pagelog_end) FROM pagelog
ORDER BY DATEDIFF(s, pagelog_created, pagelog_end) DESC
根据我所知,返回最大值30837,即8.5小时或30,837,000毫秒,完全在SQL INT的范围内?
任何帮助都会非常感激,据我所知,我有两个选择:
谢谢!
答案 0 :(得分:2)
这里的问题不是大范围,而是负范围。这显然会导致负溢出。如果SQL Server错误更具描述性,但在技术上并不错误,那将会很有帮助。
所以在我的情况下,这是返回值:
SELECT * FROM pagelog
WHERE pagelog_created > pagelog_end
删除值,或从初始结果集中省略它们!
感谢Ivan G和Andriy M的回复
答案 1 :(得分:1)
您可以尝试避免这样的溢出:
DECLARE @dt1 DATETIME = '2013-01-01 00:00:00.000'
DECLARE @dt2 DATETIME = '2013-06-01 23:59:59.997'
SELECT DATEDIFF(DAY, CAST(@dt1 AS DATE), CAST(@dt2 AS DATE)) * 24 * 60 * 60
SELECT DATEDIFF(ms, CAST(@dt1 AS TIME), CAST(@dt2 AS TIME))/1000.0
SELECT DATEDIFF(DAY, CAST(@dt1 AS DATE), CAST(@dt2 AS DATE)) * 24 * 60 * 60
+ DATEDIFF(ms, CAST(@dt1 AS TIME), CAST(@dt2 AS TIME))/1000.0
首先它从DATE
的{{1}}部分获取整天的秒数,然后它会增加DATETIME
部分的秒数,之后,它只是添加它们。
不会出现错误,因为TIME
DATEDIFF
数据类型中的最短和最长时间不会产生溢出。
答案 2 :(得分:0)
你当然可以这样做:
SELECT
DATEDIFF(ms, DATEADD(s, x.sec, pagelog_created), pagelog_end) * 0.001
+ x.sec AS pl_duration
FROM pagelog
CROSS APPLY (
SELECT DATEDIFF(s, pagelog_created, pagelog_end)
) x (sec)
;
如您所见,首先,取pagelog_created
和pagelog_end
之间的秒数差异,然后将秒添加回pagelog_created
以及该值与之间的差值(以毫秒为单位)计算pagelog_end
并将其添加到秒。
但是,根据您的调查,该表似乎没有可能导致溢出的行,我还要仔细检查该特定片段是否是错误的来源
答案 3 :(得分:0)
with cte as(
select rownum = row_number() over(partition by T.TR_ID order by T.[date]),
T.* from [dbo].[TR_Events] T
)
select cte.[date],nex.[date],convert(varchar(10),datediff(s, cte.[date], nex.[date])/3600)+':'+
convert(varchar(10),datediff(s, cte.[date], nex.[date])%3600/60)+':'+
convert(varchar(10),(datediff(s,cte.[date], nex.[date])%60))
from cte
left join cte prev on prev.rownum = cte.rownum - 1
left join cte nex on nex.rownum = cte.rownum + 1