CEIL向上取整(不小于原数的最小整数),FLOOR向下取整(不大于原数的最大整数);二者均返回DECIMAL或DOUBLE类型而非整数,且负数处理易误解:CEIL(-2.7)=-2,FLOOR(-2.7)=-3。

CEIL 和 FLOOR 函数的基本行为差异
CEIL 向上取整(不小于原数的最小整数),FLOOR 向下取整(不大于原数的最大整数)。两者都返回 DECIMAL 或 DOUBLE 类型,不是整数类型——这点常被忽略,尤其在后续做 GROUP BY 或 JOIN 时可能因隐式类型转换出问题。
常见错误现象:SELECT CEIL(3.0) 返回 3.0 而非 3;某些数据库(如 MySQL 8.0+)对整数字面量仍保留小数位,影响字符串拼接或 JSON 输出。
- MySQL、PostgreSQL、SQL Server(2012+)、Oracle 都支持
CEIL和FLOOR,但 SQL Server 用CEILING(CEIL不可用) - SQLite 只有
ROUND,需用CAST((x + 0.999999999) AS INTEGER)模拟CEIL,且对负数要单独处理 - 参数必须是数值型,传入
NULL直接返回NULL,不会报错
处理负数时的典型陷阱
CEIL(-2.7) 是 -2(向上靠近 0),FLOOR(-2.7) 是 -3(向下远离 0)。很多人误以为“向上=变大”,但在数轴上,“向上”指代数值增大的方向,-2 > -2.7,所以 CEIL 对负数反而返回更大的数。
使用场景:计算分页页码、按价格区间分桶(如「≤50 元」、「51–100 元」)时,若用 FLOOR(price / 50),price = -10 会得到 -1,导致分组错乱。
- 安全写法:先
WHERE price >= 0过滤,或用CASE WHEN price - 避免直接对可能为负的字段调用
FLOOR做分组依据 - 测试时务必覆盖
-0.5、-1.0、0.0这几个边界值
和 ROUND 配合使用的实际需求
单纯取整不够用——比如想把 12345.6789 缩成「1.23 万」,需要先除以 10000,再 ROUND(..., 2),而不是 CEIL 或 FLOOR。但若要求「至少显示 1 万」,就得用 CEIL(val / 10000)。
性能影响:三者都是标量函数,无索引加速,大量数据上使用会强制逐行计算。若用于 WHERE 条件(如 WHERE FLOOR(created_at / 86400) = 19200),无法利用时间索引,应改用范围查询。
- 替代方案:
ROUND(x, 0)四舍五入,TRUNCATE(x, 0)(MySQL)或TRUNC(x)(PostgreSQL/Oracle)截断小数,行为类似FLOOR但对负数不同 - 精度注意:
ROUND(2.5, 0)在部分数据库中返回2(银行家舍入),而CEIL(2.5)稳定返回3 - 别写
CEIL(ROUND(x, 2))——多层嵌套无意义,ROUND已完成精度控制
跨数据库兼容写法建议
没有完全通用的写法,但可封装成视图或 CTE 规避重复逻辑。例如统一用 CEILING(SQL Server)和 CEIL(其他库),就只能靠应用层判断方言,或在 SQL 中用条件注释(仅限 MySQL/Oracle 支持)。
最容易被忽略的是浮点误差:在 PostgreSQL 中,CEIL(1.1 + 1.2) 可能返回 3 或 4,因为 1.1 + 1.2 实际是 2.3000000000000003,CEIL 结果仍是 3,但若参与比较(如 = 3)可能失败。
- 关键对策:对浮点运算结果加容差,如
CEIL(x + 1e-10)防止因精度丢失卡在整数边界左侧 - 金额类字段优先用
DECIMAL存储,避免FLOAT引入不可控误差 - 测试时用
SELECT x, x::TEXT, CEIL(x), FLOOR(x)并列查看原始值与结果,比只看最终数字更可靠

















