SQL Server ROUND函数对FLOAT类型计算结果四舍五入异常问题
问题原因
你的猜测是正确的,问题根源就是FLOAT类型的精度特性:FLOAT属于近似数值类型,无法精确存储所有十进制小数。你看到的计算结果0.90875只是数据库格式化展示后的近似值,实际存储的浮点数值可能略小于0.90875(例如0.9087499999999999),因此ROUND函数按照实际存储值计算时,就会得到0.9087而非预期的四舍五入结果,并非ROUND函数逻辑异常。
解决方法
- 方法1:临时计算时转换为精确数值类型
计算加权和前先将FLOAT类型的分数、权重字段转换为DECIMAL精确类型,保证计算过程无精度损失,即可得到正确的四舍五入结果,修改后的代码示例:
WITH RawData AS ( SELECT lngRelatedScoreID AS ID, cc.strName AS Exam, cc.dblWeighting, sci.dblModeratedComponentScorePercent AS Mark FROM tblStudentComponentInformation sci INNER JOIN tblCourseComponents cc ON sci.lngExamID = cc.lngExamID WHERE sci.lngRelatedScoreID IN (73652) ) SELECT [ID], ROUND(SUM(CAST(Mark AS DECIMAL(10,5)) * CAST(dblWeighting AS DECIMAL(10,5))), 4) AS TotalWeightedMark FROM RawData GROUP BY [ID]
- 方法2:添加极小偏移量(临时兼容方案)
如果不方便修改类型转换逻辑,可以在求和后添加一个不会影响业务精度的极小偏移值抵消浮点误差,示例:ROUND(SUM(Mark * dblWeighting) + 0.0000001, 4) - 方法3:底层字段优化(长期方案)
成绩、权重这类对精度要求高的业务数值,建议直接将表中对应字段的类型从FLOAT调整为DECIMAL,从根源上避免所有浮点精度导致的计算异常。
内容的提问来源于stack exchange,提问作者Andrew Richards
相关产品推荐
相关产品推荐

