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())

输出错误

算术溢出

但如果我将 = 更改为 >=,查询将起作用并返回输出。

TSUNIXTIMESTAMP,类似于 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 时出现算术溢出错误

SQL Server 算术溢出错误 - 将 nvarchar 转换为 datetime

SQL / Python尝试检查数据是不是已存在:将nvarchar转换为数据类型数字的算术溢出错误