SQLite等数据库中整数除法会截断小数部分,1/2结果为0。
要得到0.5,需确保至少一个操作数为浮点数,如1.0/2或CAST(1 AS REAL)/2。
MySQL默认返回小数结果,而SQLite、PostgreSQL等需显式转换。
最佳实践是使用显式类型转换确保跨数据库兼容性,避免隐式转换带来的意外结果。
mysql 解释说明 sqlite里1/2得到的不是0.5,得到的是0,只有1*1.0/2才会得到0.5
这个问题触及了 SQL 中一个非常基础且重要的概念:数据类型在算术运算中的决定规则。
核心原因:整数除法
在 SQLite (以及 MySQL、PostgreSQL、SQL Server 等大多数数据库) 中,当运算符/的两个操作数都是整数类型时,它执行的是整数除法。整数除法的结果会直接截断小数部分(向零取整),只返回整数部分。
1/2:两个操作数都是整数,结果是0.5的整数部分 →04/3:结果是1.333...的整数部分 →19/2:结果是4.5的整数部分 →4
为什么1*1.0/2能得出0.5?
这利用了隐式类型转换。SQL 在计算表达式时,会按顺序处理。
1 * 1.01是整数,1.0是数值(浮点数/实数)。为了计算乘法,SQL 会将
1隐式转换为浮点数1.0。结果:
1.0(浮点数)
1.0 / 2左操作数
1.0是浮点数,右操作数2是整数。SQL 会将
2隐式转换为浮点数2.0,然后执行浮点数除法。结果:
0.5(浮点数)
简单总结这个机制:
只要除法
/的任意一个操作数是浮点数(或计算结果为浮点数),SQL 就会执行浮点数除法,得到带小数的精确结果。
其他几种在 SQLite 中得到0.5的方法
除了1*1.0/2,以下几种写法的原理是相通的:
直接使用浮点数作为操作数
sql
SELECT 1.0/2; -- 结果是 0.5 SELECT 1/2.0; -- 结果是 0.5
显式转换类型 (最标准、最清晰的写法)
sql
-- 将整数 1 转换为浮点数类型 REAL SELECT CAST(1 AS REAL) / 2; -- 结果是 0.5 -- 使用 SQLite 特有的转换语法 SELECT 1 / 2.0; -- 或者简单地将分子或分母变成浮点数
乘以
1.0(你用的方法,很常用)sql
SELECT 1 * 1.0 / 2; -- 等价于 (1 * 1.0) / 2
跨数据库注意事项 (MySQL 和 SQLite 的差异)
虽然整数除法的规则是通用的,但不同 SQL 数据库在“默认行为”和“替代运算符”上存在差异,你需要留意:
| 数据库 | SELECT 1/2结果 | 获得浮点数结果的方法 | 备注 |
|---|---|---|---|
| SQLite | 0 | 1.0/2或CAST(1 AS REAL)/2 | 严格遵守整数除法 |
| MySQL | 0.5 | 1/2本身就返回0.5(一个DECIMAL类型) | MySQL 的/默认返回精确高精度小数。如果想做整数除法,要用DIV运算符:1 DIV 2→0 |
| PostgreSQL | 0 | 1.0/2或1::numeric/2 | 与 SQLite 行为一致 |
| SQL Server | 0 | 1.0/2或CAST(1 AS FLOAT)/2 | 与 SQLite 行为一致 |
| Oracle | 0.5 | 1/2本身就得到0.5 | 行为类似于 MySQL。做整数除法需要FLOOR(1/2) |
扩展:SQLite 中的取整函数
如果你想在得到小数结果后进行特定的取整操作,SQLite 提供了这些函数:
ROUND(1.0/2, 2)→0.5(四舍五入到指定小数位)FLOOR(1.5)→1.0(向下取整)CEIL(1.5)→2.0(向上取整)
总结与最佳实践
记住核心规则:在 SQLite 中,
/两边都是整数 → 整数除法。只要有一个是浮点数 → 浮点数除法。最佳实践:当需要精确的小数结果时,不要依赖隐式转换。最清晰、最不易出错的做法是显式转换:
sql
SELECT CAST(numerator AS REAL) / denominator FROM table;
跨数据库移植:如果你的 SQL 代码需要在 MySQL 和 SQLite 之间通用,要特别小心。在 SQLite 中
1/2是0,而在 MySQL 中是0.5。为了通用性,最好统一使用CAST(1 AS REAL)/2或1.0/2的形式。