ROUND 是什么
按指定小数位做舍入,位数可以为负,表示对整数位处理。坑点在浮点:FLOAT 与 DOUBLE 无法精确表示十进制小数,ROUND 的结果可能出人意料。金额类计算一律使用 DECIMAL 或 numeric。
基本信息
| 语法 | ROUND(x[, 小数位数]),MySQL 支持负的位数 |
|---|---|
| 精确类型 | MySQL 的 DECIMAL 与 PG 的 numeric 按“远离零”舍入 |
| 浮点类型 | FLOAT、DOUBLE 受二进制表示影响,结果可能不符合直觉 |
| PG 的 double | 按就近偶数舍入(银行家舍入),与 numeric 行为不同 |
| 典型坑 | ROUND(2.675, 2) 在浮点参数下可能得到 2.67 |
| 口径差异 | 先 SUM 再 ROUND 与逐行 ROUND 再 SUM 结果不同 |
行为演示
行为演示
SELECT ROUND(2.345, 2); -- 2.35:精确类型按远离零舍入
SELECT ROUND(2.675, 2); -- 浮点参数下可能得 2.67
SELECT ROUND(1234.5678, -2); -- 1200:MySQL 支持负位数
-- 金额场景:列定义为 DECIMAL,舍入结果才可预期
SELECT ROUND(SUM(amount), 2) AS total, -- 先汇总再舍入
SUM(ROUND(amount, 2)) AS row_wise_total -- 逐行舍入再汇总,口径不同
FROM orders;舍入行为对照
| 场景 | MySQL 8 | PostgreSQL |
|---|---|---|
| DECIMAL / numeric | 远离零舍入 | 远离零舍入 |
| FLOAT / DOUBLE | 受二进制表示影响 | double precision 就近偶数 |
| 负的位数 | 支持 ROUND(x, -2) | 同样支持 round(x, -2) |
| 取整函数 | CEIL、FLOOR、TRUNCATE | ceil、floor、trunc |
| 金额字段建议 | DECIMAL(14,2) | numeric(14,2) |
典型使用场景
- 金额、税率、折扣的舍入与展示
- 指标看板统一小数位,避免同页面精度不一致
- 百分比与分位数展示时控制精度
- 把大数值近似到百位、千位,用于粗略展示
- 报表核对:统一“在哪一层舍入”的口径
- 对账差异排查:先排查是否舍入层级不同造成
- 分账与结算:把总额按比例拆成多份,最后一份用差额补齐
- 数据修复:把历史脏小数统一舍入到规范的两位小数
舍入层级会改变结果:先汇总再舍入与逐行舍入再汇总,在大量小数运算下能差出可观金额。财务类报表必须在口径文档里写明在哪一层舍入。
分摊场景的尾差要单独处理:把 100 元按 3 份分摊,逐份 ROUND 会得到 33.33 乘 3 等于 99.99,最后一份应该用总额减去前两份之和补齐,而不是再舍入一次。
在浮点列上做金额计算是隐患:二进制无法精确表示 0.1 这类十进制小数,反复累加会积累误差。金额字段请使用 DECIMAL 或 numeric 类型。