SQL Datediff 以秒为单位,带小数位
Posted
技术标签:
【中文标题】SQL Datediff 以秒为单位,带小数位【英文标题】:SQL Datediff in seconds with decimal places 【发布时间】:2013-02-25 09:24:44 【问题描述】:我试图以秒为单位提取两个 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 的范围内?
任何帮助将不胜感激,据我所知,我有两个选择:
以某种方式解决数据问题,找到罪魁祸首 寻找不同的方法来计算值之间的差异谢谢!
【问题讨论】:
试试:CAST(DATEDIFF(ms, pagelog_created, pagelog_end) AS BIGINT)/1000.00
@Justin:溢出会在它进入演员表之前发生
@JLo - 必须有一个值导致它溢出。你能试试运行这个吗:SELECT max(DATEDIFF(s, pagelog_created, pagelog_end)) FROM pagelog
错误可能是由脚本的不同片段引起的吗?不同的脚本?
【参考方案1】:
尽管上周在这个问题上花费了数小时,但 *** 的魔法似乎奏效了,但我重新阅读了我的问题,现在已经解决了这个问题。我想我会更新答案以帮助遇到此问题的其他人。
这里的问题不是有一个大范围,而是一个负范围。这显然会导致负溢出。如果 SQL Server 错误更具描述性但在技术上并没有错,那将会很有帮助。
所以在我的例子中,这是返回值:
SELECT * FROM pagelog
WHERE pagelog_created > pagelog_end
要么删除这些值,要么从初始结果集中忽略它们!
也感谢 Ivan G 和 Andriy M 的回复
【讨论】:
这是因为问题中总是包含答案,听起来很奇怪:-)【参考方案2】:你可以尝试避免这样的溢出:
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
首先它从DATETIME
的DATE
部分获取全天的秒数,然后从TIME
部分添加秒数,之后,它只是添加它们。
不会出现错误,因为DATEDIFF
在TIME
数据类型中的最小和最大时间不会产生溢出。
【讨论】:
【参考方案3】:你当然可以这样做:
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
之间的毫秒差值,添加到秒数。
但是,根据您的调查,由于该表似乎没有可能导致溢出的行,因此我还要仔细检查该特定片段 是否是 错误的来源.
【讨论】:
【参考方案4】: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
【讨论】:
虽然这段代码可能有助于解决问题,但它并没有解释为什么和/或如何回答这个问题。提供这种额外的背景将显着提高其长期价值。请编辑您的答案以添加解释,包括适用的限制和假设。以上是关于SQL Datediff 以秒为单位,带小数位的主要内容,如果未能解决你的问题,请参考以下文章
输出以秒为单位。在 php 中转换为 hh:mm:ss 格式