在 SQL Server 中划分小数类型会导致不必要的尾随零

Posted

技术标签:

【中文标题】在 SQL Server 中划分小数类型会导致不必要的尾随零【英文标题】:dividing a decimal type in SQL Server results in unnecessary trailing zeros 【发布时间】:2015-01-18 16:26:21 【问题描述】:

当我发现一些奇怪的行为时,我正在 SQL Server 中执行一些简单的财务计算。我试图将一串数字转换为十进制类型。虽然字符串不包含小数点,但根据我的规范,我知道字符串中的最后 3 个位置应该在小数点后面。

我的第一个方法有缺陷,但结果如下:

select convert(decimal(11,3),89456123/1000) as TotalUnits

这导致 89456.000。在强制转换之前执行除法会导致小数部分被截断。

所以我将除法操作移到演员表之外,如下所示:

select convert(decimal(11,3),89456123)/1000 as TotalUnits

这导致小数点后的位置激增。它返回 89456.12300000

根据我的十进制规范,我想要 11 位数字,其中 3 位在小数点后面。现在我总共有 13 位数字,小数点后有 8 位。发生了什么?

为了得到我想要的,我想我必须双重施法,像这样:

select convert(decimal(11,3), convert(decimal(11,3),89456123)/1000)

这给出了 89456.123

事实证明,无论我除以什么,产生的小数点爆炸都是一样的。除法是将数据类型转换为双精度还是什么?

我的问题是: 为什么会发生这种情况,有没有更优雅的方法来弥补它,而不是双重转换为十进制。

编辑 我在 SO 上找到了这个 similar question,但看起来他们又是双重施法。

【问题讨论】:

这适用于 rme:select convert(decimal(11,3),89456123/1000.) 【参考方案1】:

SQL server 做整数运算,要强制它使用数字,你可以乘以 1.0

无需使用 convert 两次。这给出了 89456.123 没有双重转换。

select convert(decimal(11,3),89456123*1.0/1000) as TotalUnits

【讨论】:

答案是正确的,给了+1来平衡给-1的人。 在使用这种方法时,我还发现我可以只除以 1000.0 来触发数字结果。 @Slider345,是的,你是对的,需要一个数字字段来将结果转换为数字。【参考方案2】:

为什么convert(decimal(11,3),89456123)/1000 以小数点后 6 位结尾?规则要求它。 numeric division has rather complicated rules about the resulting type.

当您说1.0 时,您最终会得到一个表示该值的比例因子最少的数字:

SELECT SQL_VARIANT_PROPERTY(1.11, 'BaseType')
SELECT SQL_VARIANT_PROPERTY(1.11, 'Precision')
SELECT SQL_VARIANT_PROPERTY(1.11, 'Scale')
SELECT SQL_VARIANT_PROPERTY(1.11, 'TotalBytes')

你应该怎么做?由于复杂的规则,我认为没有真正优雅的解决方案。我能想到的任何解决方案都涉及对中间结果的相当疯狂的类型推断。我推荐的解决方案与 RADAR 已经给出的解决方案几乎相同:

select convert(decimal(11,3), convert(decimal(11, 3), 89456123)/1000) as TotalUnits

主要区别在于我认为用作演员表简写的*1.0“技巧”混淆了代码的含义。不过,如果您碰巧喜欢它,请随意使用它。

【讨论】:

这正是我想要弄清楚的——很好的解释,+1【参考方案3】:
select convert(decimal(11,3),89456123/CONVERT(decimal(11,3),1000))

【讨论】:

虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。

以上是关于在 SQL Server 中划分小数类型会导致不必要的尾随零的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 小数类型(float 和 decimal)小数相除求占比为1的方法

sql server 小数字段设为哪种类型?

sql server控制小数显示位数的解决办法。

sql类型 money 小数不显示开头的0

sql server 保留2位小数,如果整数 后面补0

在sql中插入小数会导致插入零数字而不是接近零的小数