MySQL除法运算保留2位小数的4种实现方法

10 次阅读

MySQL 中进行除法运算时,如果直接使用 /,结果的小数位数可能并不符合业务展示要求。比如金额占比、完成率、平均值等场景,通常需要将结果统一保留 2 位小数。MySQL 提供了多种实现方式,常见方案包括 ROUND()、FORMAT()、CAST() 与 TRUNCATE()。

一、使用 ROUND() 保留2位小数

ROUND() 是处理 MySQL 除法结果时最常用的方法,它可以对数值进行四舍五入。

基本语法:

SQL
ROUND(数值, 小数位数)

例如计算 10 ÷ 3,并保留 2 位小数:

SQL
SELECT ROUND(10 / 3, 2) AS result;

结果:

3.33

再比如计算商品销售额占总销售额的比例:

SQL
SELECT ROUND(1250 / 3680, 2) AS rate;

返回:

0.34

如果需要将结果转换为百分比,可以进一步乘以 100:

SQL
SELECT ROUND(1250 / 3680 * 100, 2) AS rate;

结果约为:

33.97

ROUND() 的特点

ROUND() 的核心特点是四舍五入。例如:

SQL
SELECT ROUND(3.456, 2);

结果:

3.46

而:

SQL
SELECT ROUND(3.454, 2);

结果:

3.45

因此,如果业务要求“保留两位小数,并按照四舍五入规则处理”,优先考虑 ROUND()。


二、使用 FORMAT() 保留2位小数

FORMAT() 可以将数字按照指定的小数位数进行格式化。

基本语法:

SQL
FORMAT(数值, 小数位数)

例如:

SQL
SELECT FORMAT(10 / 3, 2) AS result;

返回:

3.33

再看一个实际例子:

SQL
SELECT FORMAT(12345 / 100, 2) AS amount;

结果:

123.45

与 ROUND() 不同,FORMAT() 更偏向于显示格式处理。例如:

SQL
SELECT FORMAT(1234567.8, 2);

通常会得到:

1,234,567.80

这里不仅保留了 2 位小数,还增加了千位分隔符。

FORMAT() 使用时需要注意

FORMAT() 返回的是格式化后的字符串,而不是普通数值。

例如:

SQL
SELECT FORMAT(10 / 3, 2);

虽然显示为:

3.33

但如果后续还需要进行数值计算,通常不建议过早使用 FORMAT()。

例如统计查询中:

SQL
SELECT FORMAT(SUM(price) / COUNT(*), 2)
FROM orders;

如果这个结果只是用于页面展示,那么使用 FORMAT() 很合适。

但如果后面还需要继续进行计算,建议使用:

SQL
SELECT ROUND(SUM(price) / COUNT(*), 2)
FROM orders;

简单来说:

  • ROUND():更适合数值计算;

  • FORMAT():更适合最终展示。


三、使用 CAST() 转换为 DECIMAL

如果希望除法结果具有明确的 decimal 类型,可以使用 CAST()。

基本写法:

SQL
CAST(表达式 AS DECIMAL(总位数, 小数位数))

例如:

SQL
SELECT CAST(10 / 3 AS DECIMAL(10, 2)) AS result;

结果:

3.33

对于数据库中的实际字段,这种方式尤其常见。

例如有一张订单表:

SQL
CREATE TABLE orders (
    id INT PRIMARY KEY,
    total_amount DECIMAL(10, 2),
    quantity INT
);

现在需要计算平均商品金额:

SQL
SELECT
    id,
    CAST(total_amount / quantity AS DECIMAL(10, 2)) AS average_amount
FROM orders;

这样可以明确控制结果的数据类型和小数位数。

CAST() 与 ROUND() 的区别

两者都可以实现保留 2 位小数,但侧重点不同。

SQL
SELECT ROUND(10 / 3, 2);

重点是对计算结果进行四舍五入。

而:

SQL
SELECT CAST(10 / 3 AS DECIMAL(10, 2));

重点是将结果转换为指定的 DECIMAL 类型。

如果数据库字段本身是 DECIMAL,或者结果需要继续参与精确的金额计算,使用 DECIMAL 类型通常更加合理。


四、使用 TRUNCATE() 截取2位小数

如果业务不是要求四舍五入,而是要求直接截断多余的小数,可以使用 TRUNCATE()。

基本语法:

SQL
TRUNCATE(数值, 小数位数)

例如:

SQL
SELECT TRUNCATE(10 / 3, 2) AS result;

结果:

3.33

再看一个更容易体现区别的例子:

SQL
SELECT
    ROUND(3.456, 2) AS round_result,
    TRUNCATE(3.456, 2) AS truncate_result;

结果分别为:

3.46
3.45

可以看到,ROUND() 会进行四舍五入,而 TRUNCATE() 只是截掉 2 位小数之后的内容。

TRUNCATE() 适合什么场景?

例如某些业务规定:

计算结果只取小数点后两位,不进行四舍五入。

这时可以使用:

SQL
SELECT TRUNCATE(numerator / denominator, 2)
FROM table_name;

不要用 ROUND() 替代,否则可能改变最终结果。


五、MySQL除法中的整数问题

处理除法时,还有一个容易被忽略的问题:操作数的数据类型会影响结果。

例如:

SQL
SELECT 10 / 3;

通常可以得到带小数的结果:

3.3333

而使用整数除法运算符 DIV:

SQL
SELECT 10 DIV 3;

结果则是:

3

因此,如果目标是保留 2 位小数,就不能使用 DIV:

SQL
SELECT ROUND(10 DIV 3, 2);

得到的仍然是:

3.00

因为 DIV 在前一步已经完成了整数除法。

正确做法应该是:

SQL
SELECT ROUND(10 / 3, 2);

结果:

3.33

六、实际业务中的除法保留2位小数

假设有一张销售表:

SQL
CREATE TABLE sales (
    id INT PRIMARY KEY,
    sale_amount DECIMAL(12, 2),
    order_count INT
);

现在需要计算每笔记录的平均订单金额。

可以写成:

SQL
SELECT
    id,
    sale_amount,
    order_count,
    ROUND(sale_amount / order_count, 2) AS average_amount
FROM sales;

如果需要计算销售完成率:

SQL
SELECT
    ROUND(completed_count / total_count * 100, 2) AS completion_rate
FROM statistics;

不过这里存在一个实际问题:如果 total_count 为 0,就可能产生除零问题。

更稳妥的写法是:

SQL
SELECT
    ROUND(completed_count / NULLIF(total_count, 0) * 100, 2) AS completion_rate
FROM statistics;

NULLIF(total_count, 0) 在 total_count 为 0 时返回 NULL,从而避免直接执行除零运算。

也可以使用 CASE:

SQL
SELECT
    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

从数值意义上看基本等价,但展示形式不同。

这种情况下可以使用:

SQL
SELECT FORMAT(3.3, 2);

得到:

3.30

而:

SQL
SELECT 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位小数的选择建议

如果只是普通的数据计算,推荐优先使用:

SQL
ROUND(字段1 / 字段2, 2)

如果结果需要明确作为 DECIMAL 类型参与后续处理,可以考虑:

SQL
CAST(字段1 / 字段2 AS DECIMAL(10, 2))

如果需求明确规定“不进行四舍五入”,则使用:

SQL
TRUNCATE(字段1 / 字段2, 2)

如果 SQL 查询的最终目的就是生成报表或页面展示,并且要求始终显示两位小数,可以使用:

SQL
FORMAT(字段1 / 字段2, 2)

对于金额、比例、统计数据等业务场景,还应该特别关注除数为 0、数据类型、精度以及最终展示格式,避免只关注小数位数而忽略计算本身的准确性。