关于Mysql的float字段的比较处理
作/译者:吴炳锡 来源:http://coolriver.cublog.cn,wubingxi#gmail.com
首先声明:Mysql手册上已经说明,FLOAT或DOUBLE列与具有数值类型的数值进行比较,不能使用等式(=)比较.
但实际还有这种需要.
今天就来研究一下float,double 字段在where 字段中的处理.
>desc olympic_result;
+---------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | | PRI | NULL | auto_increment |
| user_id | int(10) unsigned | | | 0 | |
| types | tinyint(4) | | | 0 | |
| result | float | | MUL | 0 | |
| times | int(10) unsigned | | | 0 | |
+---------+------------------+------+-----+---------+----------------+
> select * from olympic_result;
+----+---------+-------+--------+-----------+
| id | user_id | types | result | times |
+----+---------+-------+--------+-----------+
| 1 | 243 | 1 | 10.28 | 143243242 |
+----+---------+-------+--------+-----------+
> select * from olympic_result where result=10.28;
Empty set (0.00 sec)
>Why?
让我们看一下:
>alter table olympic_result add cresutl varchar(32);
>update olympic_result set cresult=10.28 where id=1;
mysql> select * from olympic_result;
+----+---------+-------+--------+-----------+-------------------------+
| id | user_id | types | result | times | cresult |
+----+---------+-------+--------+-----------+-------------------------+
| 1 | 243 | 1 | 10.28 | 143243242 | 10.27999973297119140625 |
可以看到10.28,这样的浮点值在电脑存放为10.27999973297119140625 这种形式.
听高手讲是:因为10进制和2进制之间的误差.看样子误差也在第七位出现了.所以小数据保留七位或是八位是有依据的.
在大多数计算机语言中,该问题很常见,这是因为,并非所有的浮点值均能以准确的精度保存。在某些情况下,将FLOAT更改为DOUBLE可更正该问题。
解决方法:
第一个是用区间:
select * from olympic_result where result>10.27 and result<10.29;
第二个就是在设计根本不设计float型的字段,而是用一个int型+标识这个int型的小数位来代替float型,也就是result=10.28在数据库中存的是result=10.28,precision=2
缺点:但这种方法,排序时,不好解决.
第三个方法:设计时多做一个字符字段:
如:alter table olympic_result add cresutl varchar(32);
插入更新时,加上引号.
>update olympic_result set cresult='10.28' where id=1;
这样去处理.
查询:
mysql> select * from olympic_result where cresult='10.28';
+----+---------+-------+--------+-----------+---------+
| id | user_id | types | result | times | cresult |
+----+---------+-------+--------+-----------+---------+
| 1 | 243 | 1 | 10.28 | 143243242 | 10.28 |
+----+---------+-------+--------+-----------+---------+
排序时可以按result进行.
思考:
如果小数点后面位数固定可以用decimal类型.也可以解决问题.