SQL Server 如何确定精度/小数位数?

cpa*_*eco 8 sql-server t-sql sql-server-2012 decimal

我正在运行 SQL Server 2012

SELECT 
   0.15 * 30 / 360,
   0.15 / 360 * 30 
Run Code Online (Sandbox Code Playgroud)

结果:

 0.012500, 
 0.012480
Run Code Online (Sandbox Code Playgroud)

这个对我来说更令人困惑:

DECLARE @N INT = 360
DECLARE @I DECIMAL(38,26) = 0.15 * 30 / 360     
DECLARE @C DECIMAL(38,26) = 1000000     

SELECT @C *  @I *  POWER(1 + @I, @N)  / ( POWER(1 + @I, @N) - 1 )
SELECT @C * (@I *  POWER(1 + @I, @N)  / ( POWER(1 + @I, @N) - 1 ) )
Run Code Online (Sandbox Code Playgroud)

第一个选择给了我正确的结果:12644.44022 第二个截断结果:12644.00000

Aar*_*and 14

确定表达式产生的精度和比例是一个老鼠窝,我认为没有人了解每种情况下的确切规则,尤其是在混合使用小数(或浮点数!)和整数时。请参阅gbn 的这个答案

您当然可以通过进行更详细的显式转换来定制表达式以提供您想要的内容。这可能有点矫枉过正,但是:

SELECT 
   CONVERT(DECIMAL(15,6), CONVERT(DECIMAL(15,6), 0.15) 
   * CONVERT(DECIMAL(15,6), 30) 
   / CONVERT(DECIMAL(15,6), 360)),
   CONVERT(DECIMAL(15,6), CONVERT(DECIMAL(15,6), 0.15) 
   / CONVERT(DECIMAL(15,6), 360) 
   * CONVERT(DECIMAL(15,6), 30));
Run Code Online (Sandbox Code Playgroud)

由于浮点数学运算错误或精度/比例严重错误,这两个结果都不会被错误地舍入。

0.012500    0.012500
Run Code Online (Sandbox Code Playgroud)


Oli*_*ner 6

正如 Aaron Bertrand 所提到的,表达式很难预测。

如果你敢去那里,你可以尝试使用以下代码片段获得一些见解:

DECLARE @number SQL_VARIANT
SELECT @number = 0.15 / 360
SELECT @number
SELECT  
    SQL_VARIANT_PROPERTY(@number, 'BaseType') BaseType,
    SQL_VARIANT_PROPERTY(@number, 'MaxLength') MaxLength,
    SQL_VARIANT_PROPERTY(@number, 'Precision') Precision
Run Code Online (Sandbox Code Playgroud)

这是结果:

------------
0.000416

(1 row(s) affected)

BaseType     MaxLength    Precision
------------ ------------ ----------
numeric      5            6

(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)