如何在T-SQL中提取money格式列的精确小数部分?
解决SQL Server中Money类型提取精确小数位的问题
问题根源
直接将money类型转换为varchar时,SQL Server会自动对数值进行四舍五入并格式化为两位小数,导致原始多位数小数的精度丢失,这也是parsename函数只能提取到四舍五入后两位小数的原因。
可行解决方案
方案1:转换为Decimal类型后用Parsename提取
先将money转换为decimal(19,4)(money类型最多支持4位小数,该精度可完整保留原始数值),再通过parsename获取小数部分:
select home_currency_amount, parsename(cast(home_currency_amount as decimal(19,4)), 1) as exact_decimal_part from #temptbl;
执行输出示例:
| home_currency_amount | exact_decimal_part |
|---|---|
| 39396.855 | 8550 |
| 1112.465 | 4650 |
| 5635.1824 | 1824 |
若需要去除末尾无意义的0,可嵌套
cast(...) as int或trim函数处理。
方案2:通过数值计算提取小数位
利用数学运算分离整数与小数部分,避免字符串转换带来的精度损失:
select home_currency_amount, cast((home_currency_amount - floor(home_currency_amount)) * 10000 as int) as exact_decimal_part from #temptbl;
该方法通过floor获取整数部分,用原数值减去整数部分得到纯小数,乘以10000(对应money的最大小数位数)后转成整数,直接得到完整的小数位数字。
方案3:提取与原始小数位数一致的结果
如果需要输出和原始数值小数位数完全匹配的结果(如39396.855返回855,5635.1824返回1824),可结合convert指定格式避免四舍五入,再通过字符串截取实现:
select home_currency_amount, replace(rtrim(replace(parsename(cast(home_currency_amount as decimal(19,4)), 1), '0', ' ')), ' ', '0') as exact_decimal_part from #temptbl;
该方法先保留完整小数位,再通过替换、去空格操作去除末尾的0,最终得到与原始数值小数位数一致的结果。
内容的提问来源于stack exchange,提问作者Prash
相关产品推荐
相关产品推荐

