round()按第二参数四舍五入:0为个位,正数保留小数位,负数向左取整;float类型因二进制精度可能导致结果异常,应转decimal;mysql不支持银行家舍入;group by中round易因浮点误差分组不准。

ROUND函数的基本用法和参数含义
ROUND() 在 MySQL 中不是简单“四舍五入到整数”,它的行为由第二个参数决定。不传第二个参数时,默认为 0,即四舍五入到个位;传入正数(如 1、2)表示保留小数点后几位;传入负数(如 -1)则向左取整(十位、百位等)。
常见误用是以为 ROUND(3.14159) 会返回 3.14 —— 实际返回 3。要保留两位小数,必须显式写 ROUND(3.14159, 2)。
-
ROUND(123.456, 0)→123 -
ROUND(123.456, 2)→123.46 -
ROUND(123.456, -1)→120(四舍五入到十位)
浮点数精度导致的 ROUND 结果意外
MySQL 的 DECIMAL 和 FLOAT/DOUBLE 类型在存储时存在本质差异:FLOAT 是二进制近似存储,哪怕看起来是 1.25,底层可能存的是 1.2499999999999999。这时 ROUND(1.25, 1) 可能返回 1.2 而非预期的 1.3。
解决办法很直接:把参与 ROUND() 的字段或表达式先转成 DECIMAL。
- 错误写法:
ROUND(price * 1.08, 2)(若price是FLOAT) - 稳妥写法:
ROUND(CAST(price AS DECIMAL(10,2)) * 1.08, 2) - 或者定义列时就用
DECIMAL(10,2),避免源头漂移
ROUND 与银行家舍入(四舍六入五成双)无关
MySQL 的 ROUND() 是传统“四舍五入”,不是银行家舍入。例如 ROUND(2.5, 0) 返回 3,ROUND(3.5, 0) 返回 4,没有向偶数靠拢的逻辑。
如果业务明确要求银行家舍入(比如财务系统),MySQL 原生不支持,得靠应用层处理,或用 TRUNCATE() + 条件判断模拟,但成本高、易出错。更现实的做法是确认是否真需要——多数场景 ROUND() 就够用。
-
ROUND(1.5)→2 -
ROUND(2.5)→3 -
ROUND(0.5)→1
在 GROUP BY 或聚合中使用 ROUND 的陷阱
当对 ROUND(col, 2) 进行 GROUP BY 时,要注意:分组依据是四舍五入后的值,不是原始值。这意味着原始值相差很小(比如 1.234 和 1.235)可能被归到同一组,也可能因浮点误差被拆开。
尤其在金额统计中,这种“表面相同、实际不同”的分组可能漏掉本该合并的数据。
- 安全做法:先用
CAST(... AS DECIMAL)统一精度,再ROUND - 验证手段:加一列
col原始值,对比ROUND(col, 2)是否真一致 - 避免在
WHERE中用ROUND(col, 2) = 12.34做条件,改用范围判断(如col BETWEEN 12.335 AND 12.345)
浮点类型带来的隐性误差,比函数语法本身更常引发问题。别只盯着 ROUND() 写没写对参数,先看数据从哪来、以什么类型存。











