我认为应该了解幕后发生的事情,以供将来在类似情况下参考。
不包括科学记数法的带小数点的文字数值表示 Decimal 数据类型,该数据类型存储为尽可能小的 Decimal 类型。与 Lieven Keersmaekers 的引用相同:
https ://msdn.microsoft.com/en-us/library/ms191530%28SQL.90%29.aspx#_decimal
在 Transact-SQL 语句中,带小数点的常量会自动转换为数字数据值,使用所需的最小精度和小数位数。例如,常数 12.345 被转换为精度为 5、小数位数为 3 的数值。
小数点右侧的尾随零指定比例。小数点左边的前导零被忽略。
一些例子:
1.0 -> Decimal(2,1)
60.0 -> Decimal(3,1)
1.00 -> Decimal(3,2)
01.0 -> Decimal (2,1)
要考虑的另一点是数据类型优先级。当运算符组合不同数据类型的两个表达式时,数据类型优先级规则指定将具有较低优先级的数据类型转换为具有较高优先级的数据类型。还有一点要考虑的是,如果我们对 Decimal 类型进行算术运算,那么得到的 Decimal 类型,即精度和小数位数取决于操作数和运算本身。这在文档Precision、Scale 和 Length中有描述。
所以,括号中的部分表达式
( 1.0 / 60.0 ) is evaluated to 0.016666 and the resulting type is Decimal (8,6)
使用上述有关小数表达式的精度和比例的规则。此外,使用银行家的四舍五入或四舍五入。重要的是要注意使用了 Decimal 和 float 类型的不同舍入。如果我们继续表达
1.0 / 0.016666 is evaluated to 60.002400096 and the resulting type is Decimal (17,10)
因此,差异的部分原因是用于十进制类型的舍入与浮点类型不同。
根据上述规则,在括号内只使用一个转换就足够了。根据数据类型优先级规则,所有其他文字都将被提升为浮动。
1.0 / (1.0 / cast(60.0 as float))
还有一件重要的事情。即使这个浮点表达式也不能计算出准确的结果。只是为了让前端(SSMS 或其他)将值四舍五入(我猜)精度为 6 位,然后截断尾随零。因此,即 1.000001 变为 1。
很简单,不是吗?