算术溢出取决于按列分组

Joh*_*han 1 sql sql-server arithmetic-overflow

我收到此错误,但仅在按特定列分组时出现:

Arithmetic overflow error converting expression to data type int.
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么。这是导致它的查询(总和函数是罪魁祸首):

SELECT  a.AtgardAvvattningId, 
        a.ObjektId,
        sum(p.SlutLopLangd - p.StartLopLangd) As TotalLangd
    FROM AtgardAvvattning a 
        INNER JOIN Objekt o ON o.ObjektId = a.ObjektId 
        INNER JOIN Position p ON p.AvvattningAtgardId = a.AtgardAvvattningId 
        INNER JOIN Vna v ON v.PositionId = p.PositionId 
    WHERE v.OID IN (...) 
    GROUP BY a.AtgardAvvattningId, a.ObjektId, o.AtgardsDatum
    ORDER BY a.ObjektId
Run Code Online (Sandbox Code Playgroud)

p.SlutLopLangd 和 p.StartLopLangd 都是 int 列。如果我在求和之前将值转换为 bigint,它会起作用:

    sum(CONVERT(bigint, p.SlutLopLangd - p.StartLopLangd)) As TotalLangd
Run Code Online (Sandbox Code Playgroud)

给出这个结果:

AtgardAvvattningId 对象ID 总面积
直流9... 9B2... 25684
儿童早期发展... 9B2... 25700
3D0... 9B2... 170005
959... 9B2... 170005
商务英语考试... 214... 11814
C31... 214... 11815

正如您所看到的,没有任何总和接近 int 的限制。奇怪的是,如果我像这样在 group by 子句中包含positionId,它不会引发错误:

SELECT  a.AtgardAvvattningId, 
        a.ObjektId,
        sum(p.SlutLopLangd - p.StartLopLangd) As TotalLangd
    FROM AtgardAvvattning a 
        INNER JOIN Objekt o ON o.ObjektId = a.ObjektId 
        INNER JOIN Position p ON p.AvvattningAtgardId = a.AtgardAvvattningId 
        INNER JOIN Vna v ON v.PositionId = p.PositionId 
    WHERE v.OID IN (...) 
    GROUP BY a.AtgardAvvattningId, a.ObjektId, o.AtgardsDatum, p.PositionId
    ORDER BY a.ObjektId
Run Code Online (Sandbox Code Playgroud)

在本例中,AtgardAvvattning 和 Position 之间是一对一的关系。此查询给出与上面完全相同的结果。

当值如此小时,为什么它首先会引发算术溢出?为什么它在第二个中起作用?有什么不同?我知道如果没有数据和表结构可能很难给出答案,但任何提示都会有所帮助。

更新:

使用此查询完全删除组时:

    SELECT  a.AtgardAvvattningId, 
            a.ObjektId,
            p.PositionId,
            v.VnaId,
            p.StartLopLangd,
            p.SlutLopLangd,
            p.SlutLopLangd - p.StartLopLangd as Subtraction
        FROM AtgardAvvattning a 
            INNER JOIN Objekt o ON o.ObjektId = a.ObjektId 
            INNER JOIN Position p ON p.AvvattningAtgardId = a.AtgardAvvattningId 
            INNER JOIN Vna v WITH (NOLOCK) ON v.PositionId = p.PositionId 
        WHERE v.OID IN (...) 
        ORDER BY a.ObjektId
Run Code Online (Sandbox Code Playgroud)

结果根本没有很多行:

AtgardAvvattningId 对象ID 职位编号 虚拟现实 启动LopLangd 荡妇LopLangd 减法
DC96... 9B2... 第473章 1345183 168501 174922 6421
ECD4... 9B2... 07E... 1252649 74602 81027 6425
ECD4... 9B2... 07E... 1252651 74602 81027 6425
ECD4... 9B2... 07E... 1252652 74602 81027 6425
ECD4... 9B2... 07E... 1252650 74602 81027 6425
DC96... 9B2... 第473章 1345180 168501 174922 6421
DC96... 9B2... 第473章 1345181 168501 174922 6421
DC96... 9B2... 第473章 1345182 168501 174922 6421
3D08... 公元前9年... F18... 1374284 199000 233001 34001
3D08... 公元前9年... F18... 1374283 199000 233001 34001
9590... 公元前9年... A2D... 1374285 16591 50592 34001
9590... 公元前9年... A2D... 1374286 16591 50592 34001
9590... 公元前9年... A2D... 1374287 16591 50592 34001
9590... 公元前9年... A2D... 1374289 16591 50592 34001
9590... 公元前9年... A2D... 1374288 16591 50592 34001
3D08... 公元前9年... F18... 1374281 199000 233001 34001
3D08... 公元前9年... F18... 1374280 199000 233001 34001
3D08... 公元前9年... F18... 1374282 199000 233001 34001
C31B... 214... B20... 1349999 32756 44571 11815
BEC3... 214... F21... 1349998 205022 216836 11814

无论您如何对行求和,都应该很难达到 int 溢出限制。

use*_*983 6

最终值实际上并不重要。可能发生的情况是,在您的某个时刻,SUM您超过了 an 的最大值 (2,147,483,647) 或最小值 (-2,147,483,648)int并出现错误。

举个例子:

SELECT SUM(V.I)
FROM (VALUES(2147483646),
            (2),
            (-2006543543))V(I);
Run Code Online (Sandbox Code Playgroud)

这可能会产生相同的错误:

将表达式转换为数据类型 int 时出现算术溢出错误。

然而,结果SUM将是 140,940,105(远低于最大值)。这是因为如果 2147483646先将和2相加,则得到2147483648,它大于 an 的最大值int。如果您先CAST/CONVERT该值,则不会收到错误:

SELECT SUM(CONVERT(bigint,V.I))
FROM (VALUES(2147483646),
            (2),
            (-2006543543))V(I);
Run Code Online (Sandbox Code Playgroud)

  • @Johan查询文本中的任何更改都可能导致不同的计划(以及可能不同的估计,哪些行和多少行将流入和流出任何运算符,使用哪些运算符,可能发生隐式转换,之前执行哪些计算或经过任何过滤等)。[昨天类似的问题,关于字符串长度与数值范围](/sf/answers/4953917461/)。 (2认同)