三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

mysql 解释说明 sqlite里1/2得到的不是0.5,得到的是0,只有1*1.0/2才会得到0.5

mysql 解释说明 sqlite里1/2得到的不是0.5,得到的是0,只有1*1.0/2才会得到0.5

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的整数部分 →0

  • 4/3:结果是1.333...的整数部分 →1

  • 9/2:结果是4.5的整数部分 →4


为什么1*1.0/2能得出0.5

这利用了隐式类型转换。SQL 在计算表达式时,会按顺序处理。

  1. 1 * 1.0

    • 1是整数,1.0是数值(浮点数/实数)。

    • 为了计算乘法,SQL 会将1隐式转换为浮点数1.0

    • 结果:1.0(浮点数)

  2. 1.0 / 2

    • 左操作数1.0是浮点数,右操作数2是整数。

    • SQL 会将2隐式转换为浮点数2.0,然后执行浮点数除法

    • 结果:0.5(浮点数)

简单总结这个机制:

只要除法/的任意一个操作数是浮点数(或计算结果为浮点数),SQL 就会执行浮点数除法,得到带小数的精确结果。

其他几种在 SQLite 中得到0.5的方法

除了1*1.0/2,以下几种写法的原理是相通的:

  1. 直接使用浮点数作为操作数

    sql

    SELECT 1.0/2; -- 结果是 0.5 SELECT 1/2.0; -- 结果是 0.5
  2. 显式转换类型 (最标准、最清晰的写法)

    sql

    -- 将整数 1 转换为浮点数类型 REAL SELECT CAST(1 AS REAL) / 2; -- 结果是 0.5 -- 使用 SQLite 特有的转换语法 SELECT 1 / 2.0; -- 或者简单地将分子或分母变成浮点数
  3. 乘以1.0(你用的方法,很常用)

    sql

    SELECT 1 * 1.0 / 2; -- 等价于 (1 * 1.0) / 2

跨数据库注意事项 (MySQL 和 SQLite 的差异)

虽然整数除法的规则是通用的,但不同 SQL 数据库在“默认行为”和“替代运算符”上存在差异,你需要留意:

数据库SELECT 1/2结果获得浮点数结果的方法备注
SQLite01.0/2CAST(1 AS REAL)/2严格遵守整数除法
MySQL0.51/2本身就返回0.5(一个DECIMAL类型)MySQL 的/默认返回精确高精度小数。如果想做整数除法,要用DIV运算符:1 DIV 20
PostgreSQL01.0/21::numeric/2与 SQLite 行为一致
SQL Server01.0/2CAST(1 AS FLOAT)/2与 SQLite 行为一致
Oracle0.51/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(向上取整)

总结与最佳实践

  1. 记住核心规则:在 SQLite 中,/两边都是整数 → 整数除法。只要有一个是浮点数 → 浮点数除法。

  2. 最佳实践:当需要精确的小数结果时,不要依赖隐式转换。最清晰、最不易出错的做法是显式转换

    sql

    SELECT CAST(numerator AS REAL) / denominator FROM table;
  3. 跨数据库移植:如果你的 SQL 代码需要在 MySQL 和 SQLite 之间通用,要特别小心。在 SQLite 中1/20,而在 MySQL 中是0.5。为了通用性,最好统一使用CAST(1 AS REAL)/21.0/2的形式。

← 返回列表