在 MySQL 8.0.21 上,我有一个空表 (Tbl
),其中有一列:num
,类型为 float
。
我插入一行,其值为 0.1
:
INSERT INTO Tbl(num) VALUES(0.1)
我运行以下查询并获得预期值0.1
:
SELECT MAX(num) FROM Tbl
现在,我运行一个查询,我认为该查询在语义上与第一个查询等效,并得到0.10000000149011612
:
SELECT MAX(IF(TRUE, num, 0)) FROM Tbl
有趣的是,如果没有 MAX
,这种行为就不会重现,即以下返回 0.1
:
SELECT IF(TRUE, num, 0) FROM Tbl
我知道 float 并不总是能够准确表示,并且我理解为什么算术运算会导致此类问题,但为什么要在 MAX
中使用这个 IF
有什么不同吗?
最佳答案
它们返回不同的类型。当您使用 MAX() 时,它将浮点值上采样为 double :
CREATE TABLE T_MAX AS SELECT MAX(IF(TRUE, num, 0)) AS max_num FROM Tbl;
mysql> SHOW CREATE TABLE T_MAX\G
*************************** 1. row ***************************
Table: T_MAX
Create Table: CREATE TABLE `T_MAX` (
`max_num` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE T_IF AS SELECT IF(TRUE, num, 0) AS if_num FROM Tbl;
mysql> SHOW CREATE TABLE T_IF\G
*************************** 1. row ***************************
Table: T_IF
Create Table: CREATE TABLE `T_IF` (
`if_num` float DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
我们可以在不执行 MAX() 的情况下从 float 转换为 double 并看到相同的效果:
mysql> SELECT CAST(num AS DOUBLE) AS dblnum FROM TBL;
+---------------------+
| dblnum |
+---------------------+
| 0.10000000149011612 |
+---------------------+
请注意,如果我们将原始存储的 num 设为 double,则不需要进行转换,因此不会更改表示形式。
CREATE TABLE TBL2 (num DOUBLE);
INSERT INTO TBL2 (num) VALUES (0.1);
SELECT MAX(IF(TRUE, num, 0)) AS num FROM TBL2;
+------+
| num |
+------+
| 0.1 |
+------+
因此,正是 float 到 double 的转换引起了问题。
关于MySQL 疯狂的(?)浮点行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63659098/