SQL Server Decimal舍入问题:无法实现4位小数正确舍入
保留4位小数并舍入的SQL问题解决
需求
将Col1的计算结果保留4位小数,并对第4位小数进行舍入,但现有SQL语句未得到预期效果。
尝试的SQL语句
select a + ISNULL(b,0) + ISNULL(c, 0) as col1, convert(money, a + ISNULL(b,0) + ISNULL(c, 0)) as col2, convert(decimal(19, 4), a + ISNULL(b,0) + ISNULL(c, 0)) as col3, round(a + ISNULL(b,0) + ISNULL(c, 0),4) as col4 from table1
实际查询结果
col1 col2 col3 col4 170932.96505 170932.965 170932.9650 170932.965 293944.57535 293944.5753 293944.5753 293944.5753 116913.64795 116913.6479 116913.6479 116913.6479 15975.13135 15975.1313 15975.1313 15975.1313
预期结果(col2/col3/col4)
170932.9651 293944.5754 116913.6480 15975.1314
表结构
create table test( a money, b float, c money );
示例记录
insert into test values (15541.55, 23.57135, 410.01);
问题原因及解决办法
问题根源
数据类型混合计算导致精度丢失:money类型默认仅保留4位小数,float是近似数值类型,直接相加后第5位小数的精度被抹除,使得round和转换操作无法正确识别舍入规则。
解决方案
先将所有参与计算的字段转换为高精度的decimal类型,再进行计算和舍入:
select calc_val as col1, CONVERT(decimal(19,4), ROUND(calc_val, 4)) as col2, CONVERT(decimal(19,4), ROUND(calc_val, 4)) as col3, ROUND(calc_val, 4) as col4 from ( select CAST(a as decimal(19,5)) + CAST(ISNULL(b,0) as decimal(19,5)) + CAST(ISNULL(c,0) as decimal(19,5)) as calc_val from test ) t;
说明
- 将
money和float统一转换为decimal(19,5),确保计算时保留5位小数,让第5位小数能被正确用于判断舍入逻辑。 - 使用
ROUND函数对计算结果进行4位小数舍入,再转换为decimal(19,4)保证最终结果固定保留4位小数。
内容的提问来源于stack exchange,提问作者athresh
相关产品推荐
相关产品推荐

