Azure ADF 错误算术溢出错误将表达式转换为数据类型 int
Posted
技术标签:
【中文标题】Azure ADF 错误算术溢出错误将表达式转换为数据类型 int【英文标题】:Azure ADF Error Arithmetic overflow error converting expression to data type int 【发布时间】:2022-01-02 01:53:11 【问题描述】:我正在使用 azure ADF,但在 azure ADF 上执行此查询时遇到问题:
SELECT COUNT(*) AS c
FROM TABLE
WHERE CONVERT(date, (FORMAT(DATEADD(second, CONVERT(bigint, TS) / 1000, '19700101'), 'yyyy-MM-dd'))) = CONVERT(Date, GETDATE())
输出错误
算术溢出
但如果我将 =
更改为 >=
,查询将起作用并返回输出。
TS
是 UNIXTIMESTAMP
,类似于 1637680012264
。
使用>=
和<
的组合是不行的,因为我处理的是不连续的日子(我需要使用WHERE TS IN (date1, date2, etc...)
有人可以帮我吗?提前致谢
【问题讨论】:
dateadd
已经返回了一个datetime
,你为什么用FORMAT
只重铸成date
?
@HoneyBadger 因为我需要'yyyy-MM-dd'中的日期,我不需要时间
所以 CONVERT(date, ...
... FORMAT()
到目前为止是 the worst possible way to do this。
@SalvatoreBonanno 所以?只需将dateadd
的结果转换为日期即可。
@HoneyBadger 刚试过,同样的错误
【参考方案1】:
我最好将表更改为存储datetime2
值,而不是复杂的纪元垃圾。
但是,假设您无法修复设计...
就 Larnu 而言,您不想对列应用计算,而且绝对不想将FORMAT()
应用到两边,因为FORMAT()
is an absolute dog。
相反,我会找到今天的界限,并使用一个开放式范围。这假定TS
列必须是bigint
:
DECLARE @d date = GETDATE();
DECLARE @start bigint = DATEDIFF(SECOND, '19700101', @d),
@end bigint = DATEDIFF(SECOND, '19700101', DATEADD(DAY, 1, @d));
SELECT COUNT(*) AS c
FROM dbo.[TABLE]
WHERE TS >= @start * 1000
AND TS < @end * 1000;
示例db<>fiddle
这避免了任何格式化开销、复杂和不必要的转换表达式(TS
必须已经是 bigint
,对,那么为什么要显式地使用 CONVERT()
?)。
如果您需要不连续的日期,好的,我们仍然可以通过更少的滥用表格来完成此操作。只需创建一个带有计算列的#temp 表或表变量,在其中插入多个日期,然后对其进行外部联接。
DECLARE @d table
(
d datetime2,
s AS CONVERT(bigint,
DATEDIFF(SECOND, '19700101', d)) * 1000,
e AS CONVERT(bigint,
DATEDIFF(SECOND, '19700101', DATEADD(DAY, 1, d))) * 1000
);
INSERT @d(d) VALUES('20211123'),('20211007');
-- if you want a row per day:
SELECT d.d, COUNT(t.TS) AS c
FROM @d AS d
LEFT OUTER JOIN dbo.[TABLE] AS t
ON t.TS >= d.s
AND t.TS < d.e
GROUP BY d.d
ORDER BY d.d;
-- if you just want a total count:
SELECT COUNT(t.TS) AS c
FROM @d AS d
LEFT OUTER JOIN dbo.[TABLE] AS t
ON t.TS >= d.s
AND t.TS < d.e;
示例db<>fiddle
更多关于约会的坏习惯和最佳实践:
Dating Responsibly【讨论】:
感谢 Aaron,尽管您的解决方案不是我想要的,但您用“这不是错误的根源”照亮了我的团队。DATEADD 永远无法增加 30 亿秒到 1970 年。因此,如果您只关心日期,则可以再次划分并尝试按分钟添加,第二级精度应该不重要。您能否提供一些 TS 样本值和预期结果?所以将 UNIXTIMESTAMP 转换为 DAYS 为 60*60*1000*24 @SalvatoreBonanno 但这仍然是解决问题的一种极其低效的方法。你想要 where 子句另一边的数学,相信我。除非TS
列没有被索引,并且你知道你永远不会索引它。
是的,我看到了临时表的解决方案。最有问题的东西是我只能对表具有读取权限(表在云上),所以我对它的索引一无所知(它也可能是一个视图!)。所以数学问题现在解决了这个问题,但我会按照你说的尝试优化它。【参考方案2】:
我在本地 ADF 环境中进行了复制,并能够成功获得结果。
以下是示例表:
在这里,我有 3 行日期为“2021-11-23”和 2 行日期为“2021-11-24”。 TS
列具有 UNIX 时间戳格式的日期,dt_format
列以日期格式显示 TS
列。
ADF:
使用查找活动,获取 TS 列具有今天日期的行数。 (我将您的代码与不同的表一起使用)。
SELECT COUNT(*) AS c
FROM tb1
WHERE CONVERT(date, (FORMAT(DATEADD(second, CONVERT(bigint, TS) / 1000, '19700101'), 'yyyy-MM-dd'))) = CONVERT(Date, GETDATE())
输出:
【讨论】:
以上是关于Azure ADF 错误算术溢出错误将表达式转换为数据类型 int的主要内容,如果未能解决你的问题,请参考以下文章
将 varchar 转换为数字数据类型时出现算术溢出错误。找不到存储过程''。?
将 expression 转换为数据类型 datetime 时出现算术溢出错误。
将 numeric 转换为数据类型 numeric 时出现算术溢出错误