floor返回≤当前值的最大整数,ceiling返回≥当前值的最小整数;负数时易错(如ceiling(-2.1)=-2,floor(-2.1)=-3),二者不四舍五入、不截断,对null返回null,且无法利用索引加速。

FLOOR 和 CEILING(等价于 CEIL)不是“四舍五入”,也不是“去掉小数”,它们是数学意义上的边界函数:一个找≤当前值的最大整数,一个找≥当前值的最小整数。负数时行为反直觉,这是最常出错的地方。
CEILING(-2.1) 为什么返回 -2 而不是 -3?
因为 -2 是满足 “≥ -2.1” 条件的最小整数。数轴上,-2.1 左边是 -3、-4…右边是 -2、-1…所以向上取整是往右走,不是往“绝对值变小”方向走。
-
CEILING(3.9)→ 4,FLOOR(3.9)→ 3(正数好理解) -
CEILING(-2.1)→ -2,FLOOR(-2.1)→ -3(负数必须画数轴验证) -
CEILING(0.0)和FLOOR(0.0)都返回 0;输入为NULL时两者都返回NULL,不报错但可能漏数据
在 GROUP BY 或 ORDER BY 中直接用会触发 ONLY_FULL_GROUP_BY 错误
MySQL 5.7+ 严格模式下,表达式不能替代列名参与分组或排序逻辑,除非所有非聚合字段都显式处理。
- 错误写法:
SELECT CEILING(price), name FROM products GROUP BY CEILING(price)——name既没聚合也没出现在GROUP BY中 - 正确做法之一:
SELECT CEILING(price), MAX(name) FROM products GROUP BY CEILING(price) - 更稳妥方式:用子查询隔离计算,避免语义干扰:
SELECT ceil_price, COUNT(*) FROM (SELECT CEILING(price) AS ceil_price FROM products) t GROUP BY ceil_price
和 DECIMAL 类型一起用时结果带 .00,后续比较可能隐式转换失效
CEILING 和 FLOOR 返回类型与输入一致。若输入是 DECIMAL(10,2),结果仍是 DECIMAL,显示为 124.00 而非 124。
- 这会导致跟整数字段或
SIGNED变量做=比较时触发隐式类型转换,索引可能失效 - 想得到纯整数,必须显式转换:
CAST(CEILING(x) AS SIGNED)或CONVERT(CEILING(x), SIGNED) - 对浮点字段(如
DOUBLE)直接取整后用于WHERE price = CEILING(x),同样因类型不匹配导致索引无法使用
真正容易被忽略的是:它们无法利用原始字段的索引加速
哪怕 price 字段上有 B+Tree 索引,WHERE CEILING(price) = 100 也无法走索引——MySQL 必须先计算每一行的 CEILING(price),再比对。JOIN 后的临时表、嵌套子查询中套用这些函数,也会让优化器放弃索引选择。











