ceil(-2.7)返回-2,因其返回≥-2.7的最小整数,即朝正无穷方向取整;该行为在postgresql、mysql 8.0+、sql server、oracle中完全一致,且floor与ceil是sql中唯二严格按方向取整的函数。

FLOOR 和 CEIL(或 CEILING)是 SQL 中唯二严格按方向取整的函数,不能用 ROUND 或类型转换替代。它们行为确定、跨库稳定,但容易因隐式转换、整数除法或负数理解偏差出错。
CEIL(-2.7) 为什么返回 -2?不是“进一”而是朝正无穷取整
很多人误以为 CEIL 是“加1”,其实它返回的是 ≥ 输入值的最小整数。在数轴上,-2 比 -2.7 大,-3 更小,所以 CEIL(-2.7) 必须是 -2。这个逻辑在 PostgreSQL、MySQL 8.0+、SQL Server、Oracle 中完全一致。
-
CEIL(0.001)→ 1(哪怕只多 0.001,也算一个完整单位) -
CEIL(5.0)→ 5(输入已是整数,不改变) -
CEIL(NULL)→NULL,若用于WHERE条件可能意外过滤掉整行,建议显式加WHERE col IS NOT NULL - SQL Server 只认
CEILING(),写CEIL()会报错;PostgreSQL/MySQL 支持两者,但统一用CEILING()更稳妥
FLOOR(price / 50.0) 分段统计时,为什么必须写 50.0 而不是 50?
整数除法会导致截断:比如 PostgreSQL 中 99 / 50 得 1,而 99 / 50.0 得 1.98,FLOOR(1.98) 才是 1 —— 这才是你想要的段号。如果写成整数除法,同一价格区间可能被拆成多个浮点分组,GROUP BY 失效。
- 正确写法:
FLOOR(price / 50.0) * 50 AS price_range_start - 错误写法:
FLOOR(price / 50) * 50(在多数数据库中触发整除) - 该模式同样适用于时间分桶:
FLOOR(EXTRACT(EPOCH FROM ts) / 3600)按小时分组 - 别用
ROUND(price / 50, 0)替代 —— 它四舍五入,不符合“向下归档”语义
CEILING(item_count / 12.0) 计算箱数时,为什么不能省略 .0?
整数列直接除整数,在 SQLite、SQL Server、旧版 MySQL 中会先做整除:比如 35 / 12 得 2,再 CEILING(2) 还是 2,结果漏算 1 箱。必须让除法产出浮点结果,才能让 CEILING 对小数部分起作用。
- 安全写法:
CEILING(item_count * 1.0 / 12)或CEILING(CAST(item_count AS FLOAT) / 12) - 如果字段是字符串(如
'35'),PostgreSQL 会报错function ceiling(text) does not exist,得先转数值:CEILING(col::numeric / 12.0) - 浮点型字段(如
REAL)存在二进制精度误差,建议先CAST(col AS NUMERIC)再缩放,避免0.29 * 10算成2.8999999导致CEILING错判
保留 1 位小数再向上取整,为什么不能直接 CEILING(col, 1)?
标准 SQL 不支持 CEILING 的精度参数。必须靠“缩放–取整–还原”三步走:乘以 10 → CEILING → 除以 10.0(注意是 10.0,不是 10)。
- 向上取整到 0.1:
CEILING(col * 10) / 10.0 - 向下取整到 0.01:
FLOOR(col * 100) / 100.0 - 除数写
10.0是为了防止整数除法(例如 SQL Server 中15 / 10→ 1,而15 / 10.0→ 1.5) - 这种写法也适用于金额场景:比如服务费按 0.05 元粒度向上计费,就用
CEILING(col * 20) / 20.0
真正难的不是记住函数名,而是每次写之前确认三点:输入是不是数值类型、除法有没有隐式截断、负数方向是否符合业务逻辑——尤其在计费、配额、分页这些容错率极低的场景里,差 1 就可能少收钱或多发资源。











