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;
这里的问题是"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
我在 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;
这里的问题是"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