DATEDIFF 函数导致 SQL Server 2016 溢出

DATEDIFF function resulted in an overflow in SQL Server 2016

我在 SQL Server 2016 中有一个 table,其中包含以下数据:

id     | t                       | memory
-------+-------------------------+------------
620255 | 2017-07-17 16:11:25.100 | 11632640
620127 | 2017-07-17 16:11:24.100 | 11632640
619999 | 2017-07-17 16:11:23.097 | 11632640
619872 | 2017-07-17 16:11:22.097 | 11632640

我正在尝试获取每秒 memory 的平均值。因此,为了做到这一点,我尝试了以下查询:

SELECT 
    AVG(memory) AS avgMemory, 
    DATEADD(second, DATEDIFF(second, 0, t), 0) AS t 
FROM 
    Table1 AS Table1 
WHERE 
    t BETWEEN '2017-07-17 16:11:00.000' AND '2017-07-17 16:12:00.000' 
GROUP BY 
    DATEADD(second, DATEDIFF(second, 0, t), 0) 
ORDER BY 
    t ASC;

但是在执行时,出现以下错误:

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.

根据 official docs and this SO post,秒数的最大差异可以是 68 年,但在我的例子中只有 60 秒。

那么为什么我会收到此错误?我能做些什么来解决它?

这是 SQL解决上述问题的方法:Fiddle

SQL 服务器为此目的提供 datediff_big()

SELECT AVG(memory) AS avgMemory,
       DATEADD(second, DATEDIFF_BIG(second, 0, t), 0) AS t 
FROM Table1 AS Table1 
WHERE t BETWEEN '2017-07-17 16:11:00.000' AND '2017-07-17 16:12:00.000' 
GROUP BY DATEADD(second, DATEDIFF_BIG(second, 0, t), 0) 
ORDER BY t ASC;

您也可以通过将值转换为字符串来执行此操作:

SELECT AVG(memory) AS avgMemory,
       CONVERT(VARCHAR(19), t, 120) as t
FROM Table1 AS Table1 
WHERE t BETWEEN '2017-07-17 16:11:00.000' AND '2017-07-17 16:12:00.000' 
GROUP BY CONVERT(VARCHAR(19), t, 120)
ORDER BY t ASC;

此版本适用于 SQL 服务器的所有受支持版本。

您也可以使用不同的日期(例如 2017-07-17 00:00:00.000)作为计算的固定点:

SELECT AVG(memory) AS memory, 
  DATEADD(second, 
          DATEDIFF(second, '2017-07-17 00:00:00.000', t),
          '2017-07-17 00:00:00.000') AS t 
FROM Table1 AS Table1 
WHERE t BETWEEN '2017-07-17 16:11:00.000' AND '2017-07-17 16:12:00.000' 
GROUP BY DATEADD(second, 
                 DATEDIFF(second, '2017-07-17 00:00:00.000', t), 
                 '2017-07-17 00:00:00.000') 
ORDER BY t ASC;

SQL Fiddle

这里的问题是"starting date"。

select DATEDIFF(second, 0, t)中,0表示1900-01-01离2017年太远了,所以从1900-01-01到2017-07-17的时间以秒为单位溢出了简单的整数,这不仅仅是“60 秒”

pre 2016 db,在一组依据上,我不得不将 datediff 转换为 bigint,然后获取平均值,对于 datediff by ms。 avg(cast(datediff(ms,sdate,edate)) as BIGINT)) as theavg