MySQL 中进行除法运算时,如果直接使用 /,结果的小数位数可能并不符合业务展示要求。比如金额占比、完成率、平均值等场景,通常需要将结果统一保留 2 位小数。MySQL 提供了多种实现方式,常见方案包括 ROUND()、FORMAT()、CAST() 与 TRUNCATE()。
一、使用 ROUND() 保留2位小数
ROUND() 是处理 MySQL 除法结果时最常用的方法,它可以对数值进行四舍五入。
基本语法:
SQLROUND(数值, 小数位数)
例如计算 10 ÷ 3,并保留 2 位小数:
SQLSELECT ROUND(10 / 3, 2) AS result;
结果:
3.33
再比如计算商品销售额占总销售额的比例:
SQLSELECT ROUND(1250 / 3680, 2) AS rate;
返回:
0.34
如果需要将结果转换为百分比,可以进一步乘以 100:
SQLSELECT ROUND(1250 / 3680 * 100, 2) AS rate;
结果约为:
33.97
ROUND() 的特点
ROUND() 的核心特点是四舍五入。例如:
SQLSELECT ROUND(3.456, 2);
结果:
3.46
而:
SQLSELECT ROUND(3.454, 2);
结果:
3.45
因此,如果业务要求“保留两位小数,并按照四舍五入规则处理”,优先考虑 ROUND()。
二、使用 FORMAT() 保留2位小数
FORMAT() 可以将数字按照指定的小数位数进行格式化。
基本语法:
SQLFORMAT(数值, 小数位数)
例如:
SQLSELECT FORMAT(10 / 3, 2) AS result;
返回:
3.33
再看一个实际例子:
SQLSELECT FORMAT(12345 / 100, 2) AS amount;
结果:
123.45
与 ROUND() 不同,FORMAT() 更偏向于显示格式处理。例如:
SQLSELECT FORMAT(1234567.8, 2);
通常会得到:
1,234,567.80
这里不仅保留了 2 位小数,还增加了千位分隔符。
FORMAT() 使用时需要注意
FORMAT() 返回的是格式化后的字符串,而不是普通数值。
例如:
SQLSELECT FORMAT(10 / 3, 2);
虽然显示为:
3.33
但如果后续还需要进行数值计算,通常不建议过早使用 FORMAT()。
例如统计查询中:
SQLSELECT FORMAT(SUM(price) / COUNT(*), 2) FROM orders;
如果这个结果只是用于页面展示,那么使用 FORMAT() 很合适。
但如果后面还需要继续进行计算,建议使用:
SQLSELECT ROUND(SUM(price) / COUNT(*), 2) FROM orders;
简单来说:
-
ROUND():更适合数值计算; -
FORMAT():更适合最终展示。
三、使用 CAST() 转换为 DECIMAL
如果希望除法结果具有明确的 decimal 类型,可以使用 CAST()。
基本写法:
SQLCAST(表达式 AS DECIMAL(总位数, 小数位数))
例如:
SQLSELECT CAST(10 / 3 AS DECIMAL(10, 2)) AS result;
结果:
3.33
对于数据库中的实际字段,这种方式尤其常见。
例如有一张订单表:
SQLCREATE TABLE orders ( id INT PRIMARY KEY, total_amount DECIMAL(10, 2), quantity INT );
现在需要计算平均商品金额:
SQLSELECT id, CAST(total_amount / quantity AS DECIMAL(10, 2)) AS average_amount FROM orders;
这样可以明确控制结果的数据类型和小数位数。
CAST() 与 ROUND() 的区别
两者都可以实现保留 2 位小数,但侧重点不同。
SQLSELECT ROUND(10 / 3, 2);
重点是对计算结果进行四舍五入。
而:
SQLSELECT CAST(10 / 3 AS DECIMAL(10, 2));
重点是将结果转换为指定的 DECIMAL 类型。
如果数据库字段本身是 DECIMAL,或者结果需要继续参与精确的金额计算,使用 DECIMAL 类型通常更加合理。
四、使用 TRUNCATE() 截取2位小数
如果业务不是要求四舍五入,而是要求直接截断多余的小数,可以使用 TRUNCATE()。
基本语法:
SQLTRUNCATE(数值, 小数位数)
例如:
SQLSELECT TRUNCATE(10 / 3, 2) AS result;
结果:
3.33
再看一个更容易体现区别的例子:
SQLSELECT ROUND(3.456, 2) AS round_result, TRUNCATE(3.456, 2) AS truncate_result;
结果分别为:
3.46 3.45
可以看到,ROUND() 会进行四舍五入,而 TRUNCATE() 只是截掉 2 位小数之后的内容。
TRUNCATE() 适合什么场景?
例如某些业务规定:
计算结果只取小数点后两位,不进行四舍五入。
这时可以使用:
SQLSELECT TRUNCATE(numerator / denominator, 2) FROM table_name;
不要用 ROUND() 替代,否则可能改变最终结果。
五、MySQL除法中的整数问题
处理除法时,还有一个容易被忽略的问题:操作数的数据类型会影响结果。
例如:
SQLSELECT 10 / 3;
通常可以得到带小数的结果:
3.3333
而使用整数除法运算符 DIV:
SQLSELECT 10 DIV 3;
结果则是:
3
因此,如果目标是保留 2 位小数,就不能使用 DIV:
SQLSELECT ROUND(10 DIV 3, 2);
得到的仍然是:
3.00
因为 DIV 在前一步已经完成了整数除法。
正确做法应该是:
SQLSELECT ROUND(10 / 3, 2);
结果:
3.33
六、实际业务中的除法保留2位小数
假设有一张销售表:
SQLCREATE TABLE sales ( id INT PRIMARY KEY, sale_amount DECIMAL(12, 2), order_count INT );
现在需要计算每笔记录的平均订单金额。
可以写成:
SQLSELECT id, sale_amount, order_count, ROUND(sale_amount / order_count, 2) AS average_amount FROM sales;
如果需要计算销售完成率:
SQLSELECT ROUND(completed_count / total_count * 100, 2) AS completion_rate FROM statistics;
不过这里存在一个实际问题:如果 total_count 为 0,就可能产生除零问题。
更稳妥的写法是:
SQLSELECT ROUND(completed_count / NULLIF(total_count, 0) * 100, 2) AS completion_rate FROM statistics;
NULLIF(total_count, 0) 在 total_count 为 0 时返回 NULL,从而避免直接执行除零运算。
也可以使用 CASE:
SQLSELECT CASE WHEN total_count = 0 THEN 0 ELSE ROUND(completed_count / total_count * 100, 2) END AS completion_rate FROM statistics;
具体采用哪种方式,要看业务对“总数为 0”时的结果定义。
七、除法结果强制显示两位小数
有时用户要求的并不是“数值精确到两位”,而是“页面必须显示两位小数”。
例如:
3.30
和:
3.3
从数值意义上看基本等价,但展示形式不同。
这种情况下可以使用:
SQLSELECT FORMAT(3.3, 2);
得到:
3.30
而:
SQLSELECT ROUND(3.3, 2);
返回的数值可能显示为:
3.3
因此需要区分两个概念:
保留 2 位小数与显示 2 位小数并不完全相同。
如果是财务报表、后台列表等需要固定格式的输出,FORMAT() 往往更符合展示需求。
如果结果还要参与 SQL 后续计算,则更适合使用 ROUND() 或 DECIMAL。
八、4种方法对比
| 方法 | 示例 | 核心作用 | 返回结果特点 |
|---|---|---|---|
ROUND() | ROUND(10 / 3, 2) | 四舍五入 | 数值 |
FORMAT() | FORMAT(10 / 3, 2) | 格式化显示 | 字符串 |
CAST() | CAST(10 / 3 AS DECIMAL(10,2)) | 类型转换 | DECIMAL |
TRUNCATE() | TRUNCATE(10 / 3, 2) | 直接截断 | 数值 |
实际开发中,可以按照业务目的选择:
SQL-- 四舍五入 SELECT ROUND(10 / 3, 2); -- 固定格式显示 SELECT FORMAT(10 / 3, 2); -- 转换成 DECIMAL SELECT CAST(10 / 3 AS DECIMAL(10, 2)); -- 不四舍五入,直接截断 SELECT TRUNCATE(10 / 3, 2);
九、MySQL除法保留2位小数的选择建议
如果只是普通的数据计算,推荐优先使用:
SQLROUND(字段1 / 字段2, 2)
如果结果需要明确作为 DECIMAL 类型参与后续处理,可以考虑:
SQLCAST(字段1 / 字段2 AS DECIMAL(10, 2))
如果需求明确规定“不进行四舍五入”,则使用:
SQLTRUNCATE(字段1 / 字段2, 2)
如果 SQL 查询的最终目的就是生成报表或页面展示,并且要求始终显示两位小数,可以使用:
SQLFORMAT(字段1 / 字段2, 2)
对于金额、比例、统计数据等业务场景,还应该特别关注除数为 0、数据类型、精度以及最终展示格式,避免只关注小数位数而忽略计算本身的准确性。