数据库中有一张表,表中有Float列、Double列,对Float+Double做了求和运算,通过where条件查找数据时,结果集一直是空。
具体步骤如下:
(1)先是对相加的结果进行group by
select `Float`,`Double`,IFNULL(`Float`,0)+IFNULL(`Double`,0) as dd from `laurie_data` GROUP BY dd ;
结果集如图1所示:
图1
(2)对相加结果中的0.141111通过where条件进行查找:
select dd from (select `Float`,`Double`,IFNULL(`Float`,0)+IFNULL(`Double`,0) as dd from `laurie_data`)SUB_QRY
where dd=0.141111 ;
但是过滤出来的结果集为空,如图2所示:
图2
(3)根据原表对上述现象进行分析,FLoat列和Double列有一行是0.01和0.131111(如图3所示),应该是浮点数运算的精度问题导致这两个数相加的结果不是0.141111;IFNULL(`Float`,0.0)+IFNULL(`Double`,0.0)执行的时候,应该是先把float转成了double,然后两个double相加,用java执行的结果是0.14111100000000001(如图4所示);但是如果是0.01f + 0.131111,结果是0.1411099997764826(如图5所示)
图3
图4 图5
尝试下面的SQL语句,可以过滤出指定要求的结果,如图6所示:
SELECT dd FROM (select (IFNULL(`Float`,0.0) + IFNULL(`Double`,0.0)) as dd from `laurie_data` group by DD) SUB_QRY
WHERE dd=0.14111100000000001;
图6
出现上述的情况,应该和十进制小数转二进制有关系,无限循环,导致精度值有丢失。
(4)根据上述分析,我们在SQL语句中对精度进行限制,并通过where查找,可以正常过滤出结果:
SELECT dd FROM (select (CAST(IFNULL(`Float`,0.0) AS DECIMAL(7, 6)) + CAST(IFNULL(`Double`,0.0) AS DECIMAL(7, 6))) as dd
from `laurie_data`group by DD) SUB_QRY WHERE dd=0.141111;