ceiling(-2.1)返回-2,因其返回≥-2.1的最小整数,即向正无穷取整;-2大于-2.1而-3更小,故结果为-2,该行为在postgresql、mysql 8.0+、sql server、oracle中完全一致。

CEILING(-2.1) 为什么返回 -2 而不是 -3?
因为 CEILING 永远返回 ≥ 输入值的最小整数,方向是朝正无穷,不是“进一”或“绝对值变小”。-2 比 -2.1 大,-3 更小,所以 -2 才是正确结果。这个行为在 PostgreSQL、MySQL 8.0+、SQL Server、Oracle 中完全一致。
常见错误现象:CEILING(-2.9) 写成 -3,导致分页少算一页、运费多算一档、库存预估偏高。
使用场景举例:
- 分页总页数:
CEILING(total_count / page_size) - 按 0.5kg 计费:
CEILING(weight / 0.5) * 0.5(注意除数写0.5,不是0) -
CEILING(NULL)返回NULL,不报错但可能被WHERE条件意外过滤,建议显式加WHERE col IS NOT NULL
FLOOR((page_no - 1) * page_size) 为什么不能换成 ROUND?
分页 OFFSET 必须向下取整:第 2.9 页的起始位置仍是第 2 页末尾,不是第 3 页开头。用 ROUND((page_no - 1) * page_size, 0) 会导致 page_no = 0.9 时算出 offset 0,漏掉前几条数据。
典型误用:
-
FLOOR(amount + 0.5)手动模拟四舍五入 → 在负数上完全失效(FLOOR(-2.5 + 0.5) = FLOOR(-2.0) = -2,但四舍五入应为 -3) - 价格档位归类:
FLOOR(price / 10) * 10是安全的;但FLOOR(9.99 / 10)得 0,可用来判断是否达满减门槛
字段是字符串或浮点型时怎么避免报错或精度偏差?
PostgreSQL 直接报错:function ceil(text) does not exist;浮点型如 REAL 可能因二进制精度导致 0.29 * 10 算成 2.899999999,CEILING 后得 2 而非 3。
实操建议:
- 字符串转数值:
CEIL(CAST(col AS DECIMAL))或CEIL(col::numeric) - 浮点型先转精度可控类型:
CEIL(CAST(float_col AS NUMERIC) * 10) / 10.0 - 保留一位小数再向上取整:必须缩放,
CEILING(col * 10) / 10.0(除数写10.0,否则 SQL Server 等会做整数除法)
跨数据库兼容性要注意哪些硬伤?
CEIL() 和 CEILING() 不是全库通用:CEIL() 在 MySQL/PostgreSQL/Oracle 支持;CEILING() 是 SQL Server 和旧版 MySQL 的写法;Oracle 支持 CEIL 但不认 CEILING。
关键差异点:
- SQL Server 只认
CEILING(),用CEIL()会报错 - SQLite 不支持原生
CEILING或FLOOR,CAST(x AS INTEGER)是向零截断,不是真正向上/向下取整 -
CAST(-2.7 AS INTEGER)在 PostgreSQL 中得 -2,而FLOOR(-2.7)是 -3,语义完全不同
FLOOR 和 CEILING 是 SQL 中唯二能严格按方向取整的函数,其他方式(如 ROUND、CAST、整除)在负数、边界或跨库场景下都会出错。最易被忽略的是:负数取整方向、字符串/浮点型的隐式类型转换、以及除数写 10 还是 10.0 这种细节。











