SQL Server小数除法未将结果四舍五入



我尝试了下面的乘法和除法,并期望通过舍入得到相同的结果。两个运算的结果类型均为Decimal(38,6(我想知道在除法的情况下为什么结果不四舍五入?

根据下面的链接,乘法和除法的结果都应该四舍五入在此处输入链接描述

select cast(1.225114854 as decimal(38, 9)) * cast(1.000000000 as decimal(28, 9)) as multiply 

结果:1.225115

select cast(1.225114854 as decimal(38, 9)) / cast(1.000000000 as decimal(28, 9)) as division

结果:1.225114

select 1.225114854 / 1.000000000

结果:1.22511485400000000

SQL server在小数的乘法和除法情况下的行为方式不同,因此位数的差异:

假设e1=decimal(p1,s1) and e2=decimal(p2,s2)

Operation   Result precision                        Result scale *
e1 + e2     max(s1, s2) + max(p1-s1, p2-s2) + 1     max(s1, s2)
e1 - e2     max(s1, s2) + max(p1-s1, p2-s2) + 1     max(s1, s2)
e1 * e2     p1 + p2 + 1                             s1 + s2
e1 / e2     p1 - s1 + s2 + max(6, s1 + p2 + 1)      max(6, s1 + p2 + 1)

结果精度和刻度的绝对最大值为38。当结果精度大于38时,相应的刻度会减小,以防止结果的积分部分被截断。

因此,当您乘以38个精度小数时,结果会被截断。您可以使用以下计算来获得更好的结果:

select cast(1.225114854 as decimal(15,9))*cast(1.000000000  as decimal(15,9)) as multiply
select cast(1.225114854 as decimal(15,9))/cast(1.000000000  as decimal(15,9)) as division

以下链接应该能够澄清您的大部分疑虑:

https://www.codeproject.com/Articles/769823/Losing-Precision-After-Multiplication-in-SQL-Serve

我在将SQL Server转换为Spark时遇到了同样的问题。

SQL Server和Spark使用相同的规则来确定算术运算结果的精度和小数位数,如@CR7SMS的答案所示。

我认为问题是您共享的SQL Server文档链接不正确,因为它使用了";圆形";具体地说:";结果可以四舍五入到小数点后6位;。但分裂是截断而不是循环。

我在Spark中解决了这个问题,使用了一个UDF进行划分,该UDF复制了SQL Server中的行为:

val divide = udf((x: BigDecimal, y: BigDecimal) => x.divide(y, 6, RoundingMode.FLOOR))

最新更新