使用 SUM 的算术加法序列如何在 SQL Server 中工作?

How does arithmetic sequence of addition with SUM works in SQL server?

提问人:mangerbang 提问时间:11/16/2023 最后编辑:Eric Postpischilmangerbang 更新时间:11/18/2023 访问量:64

问:

我在 SQL Server 2016 上对浮点数据类型的操作有问题。我知道浮点数据类型的加法不是关联均值,因此加法的顺序很重要,它会影响结果的准确性。然而,它只是让我想知道,它是如何工作的?我找不到任何材料来告诉我它的算术序列以及 SQL Server 如何选择顺序。SUMSUM

每当 SP 执行时,它的算术序列是否会改变?

潜在订单示例:

第一次执行:
XYZ 列下值为 A 的组 = a + b + c + d

XYZ 列下值为 B 的组 = a + c + d + b

第二次执行:
XYZ 列下值为 A 的组 = a + d + c + b

XYZ = b + c + d + a 列下值为 B 的组

请提供答案,并附有原始材料,如文献、指南、论文等。

sql-server 数学 求和 浮点聚合

评论

1赞 Tony Hopkinson 11/16/2023
如果您想要准确性,请不要使用浮点型。使用固定十进制类型。你得到的不同答案是因为某些数字不能用浮点数表示,而不是因为浮点加法在公理上不正确。
0赞 Eric Postpischil 11/17/2023
你是在问功能吗?这个文档似乎说(我不熟悉它)订单by_clause决定了订单。你所描述的“第一次处决”和“第二次处决”是什么?这些对你执行的 SQL 操作的实际观察结果,还是你虚构的假设可能性?SUM
0赞 chux - Reinstate Monica 11/17/2023
@mangerbang,“float 数据类型既不是交换,,,” --> 你是说并不总是等于吗?a + bb + a
0赞 Eric Postpischil 11/17/2023
@chux-ReinstateMonica:嗯,NaN不会总是通勤。
0赞 chux - Reinstate Monica 11/17/2023
@eric公平点。

答:

1赞 George Menoutis 11/16/2023 #1

要理解这一点,首先要阅读文档的运算符优先级

很好,所以现在您知道了下面的文本中显示的优先级和 ness。left-to-right

下一步是推断结果的数据类型。对于每个步骤,请使用适当的查询。例如,您知道将要发生的第一件事是 .您从表(或前面的步骤)中知道 a 和 b 的数据类型。您可以从以下位置找到生成的数据类型:(a+b)

exec sp_describe_first_result_set ('select a+b from yourtable')

现在您已经了解了所涉及的数据类型,现在是学习时间了。你提到了浮点数,所以你需要了解浮点运算

或者,如果你有数字/十进制,你需要定点算术。

评论

0赞 mangerbang 11/17/2023
谢谢你的回答,我非常感谢。要注意这一点。:D
0赞 David Browne - Microsoft 11/16/2023 #2

浮点数据类型的加法既是可交换的,也是关联的,在浮点数据类型的正常误差范围内。

实际上,由于硬件执行不同,浮点计算的任意两次执行的结果可能会略有不同。处理器有时会在内部使用 80 位浮点数。

评论

0赞 Eric Postpischil 11/17/2023
这个“答案”没有回答所提出的问题,即 SQL Server 计算总和的方式,特别是它使用的顺序。
0赞 Eric Postpischil 11/17/2023
在浮点数据类型的正常误差范围内,加法是关联的语句要么是错误的,要么是无用的。考虑 ,其中 x 是 2^1023。如果将其关联为 ,则结果为 1,等于实数算术结果,并且没有舍入误差。如果将其关联为 ,则结果为 +∞。因此,要么这个答案是错误的,即结果总是在“正常”误差范围内,要么“正常”误差幅度是无限的,这是无用的。x+x-x-x+1((x+(x-x))-x)+1((((x+x)-x)-x)+1)
0赞 David Browne - Microsoft 11/17/2023
真的,2^1023?它是一种具有有限数量的值的数据类型,而不是实数。所有数据类型在其最大值下都表现不佳。如果你在中间计算中越界,你会得到一个错误的结果。但这也发生在 INT 上。
0赞 Eric Postpischil 11/17/2023
是的,真的,2^1023。它可以在 SQL 类型中表示,并且是某人拥有的完全有效的数据。而且,即使没有接近类型的边界,浮点和的最终误差也会因不同的关联而有很大差异,因此这个答案是错误的或无用的,并且没有解决所提出的问题。float
0赞 David Browne - Microsoft 11/17/2023
宇宙中只有不到 2^300 个原子。
0赞 mangerbang 11/17/2023 #3

谢谢你的所有回答。我非常感谢。我几乎找到了求和顺序的概念,它位于查询计划中。

SQL首先对每个组进行排序。当我测试它时,在每个组上,数据排序看起来是随机的>然后使用流聚合对其进行处理。

--First enable "Include Actual Execution Plan" then run below query


CREATE TABLE #A (a int);
INSERT INTO #A (a) VALUES (1), (2);

CREATE TABLE #someFloats (val float);
INSERT INTO #someFloats (val) VALUES (1), (1), (1.234567), (1.2), (1.2), (3), 
(5);

SELECT #A.a, STR(SUM(#someFloats.val), 30, 25)
FROM #someFloats LEFT JOIN #A ON 1 = 1
GROUP BY #A.a;

--Look on execution plan, it mentions that it is sort by #A.a, then :
SELECT #A.a, #someFloats.val
FROM #someFloats LEFT JOIN #A ON 1 = 1
ORDER BY #A.a;

--Now we try to some based on above orders
Declare @A float = 1
Declare @B float = 1
Declare @C float = 1.234567
Declare @D float = 1.2
Declare @E float = 1.2
Declare @F float = 3
Declare @G float = 5

--The result is same
--#A.a = 1
select str((@A + @B +@C +@D +@E +@F +@G),30,15)

--#A.a = 2
select str((@G + @F +@D +@E +@C +@A +@B),30,15)

DROP TABLE #someFloats;
DROP TABLE #A;
    

看起来,Sum on SQL 正在进行相应的加法(排序后从每个组的第一行开始)。难怪,它在浮点计算上给出了不同的结果,因为订单很重要,哈哈。我在这个网站上找到了它,希望有一天能对你们有所帮助:D (https://www.red-gate.com/simple-talk/databases/sql-server/learn/showplan-operator-of-the-week-stream-aggregate/)