如何拼接两整数为带小数字符串并保留精度,找出最大组合值?
问题描述
现有如下表格:
| id | BigNumber | SmallNumber |
|---|---|---|
| 1 | 1 | 100 |
| 2 | 1 | 200 |
| 3 | 2 | 1 |
| 4 | 2 | 25 |
| 5 | 3 | 3 |
| 6 | 3 | 50 |
需求:将每行的BigNumber作为小数点左侧部分,SmallNumber作为右侧部分组合成数值(例如第1行是1.100),编写SQL查询返回符合规则的最大数值,且必须保留原始小数位(不能舍入,比如第1行需保留1.100而非1.1),上述数据应返回3.50。
我编写的查询语句如下:
select max(cast(concat(big_number,'.',small_number) as decimal)) from runs;
但该查询返回结果为4。我知道可以指定decimal(3,2)这类固定精度类型,但BigNumber和SmallNumber的位数不固定,请问如何让查询始终返回精度正确的字符串形式数值?
解决方案
核心思路是避免将组合后的字符串转为数值类型(数值类型会自动舍入或丢失小数位),而是通过字符串排序逻辑找到最大的组合值,直接返回字符串结果。
通用实现逻辑
要正确比较组合后的字符串大小,需保证:
- 优先按
BigNumber的数值降序排序(大数在前) - 当
BigNumber相同时,需将SmallNumber统一补前导零到所有SmallNumber的最大长度,再按补零后的字符串降序排序(确保数值大的小数部分排在前面,比如50比3大,补零后050比003字符串排序更靠前)
MySQL 示例代码
SELECT CONCAT(BigNumber, '.', SmallNumber) AS max_formatted_value FROM runs ORDER BY BigNumber DESC, LPAD(SmallNumber, (SELECT MAX(LENGTH(SmallNumber)) FROM runs), '0') DESC LIMIT 1;
PostgreSQL 示例代码
SELECT CONCAT(BigNumber, '.', SmallNumber) AS max_formatted_value FROM runs ORDER BY BigNumber DESC, LPAD(SmallNumber::TEXT, (SELECT MAX(LENGTH(SmallNumber::TEXT)) FROM runs), '0') DESC LIMIT 1;
代码说明
LPAD函数将SmallNumber转为字符串后,补前导零到所有SmallNumber的最大长度,确保字符串比较能准确反映小数部分的数值大小- 通过
ORDER BY先按整数部分降序,再按补零后的小数部分降序,最后取第一条结果就是符合要求的最大格式化数值 - 直接返回组合后的字符串,完全保留原始小数位,不会出现舍入或精度丢失问题
内容的提问来源于stack exchange,提问作者random55645
相关产品推荐
相关产品推荐

