同事查bug的时候发现个奇怪的bug
SQL如下
select inspection_item
where id not in (select IFNULL(item_id, '')
from plan_item
where plan_id = 3323211050993319936)
inspection_item的id字段和plan_item的id字段类型都为bigint(20)
inspection_item表数据是5条,子查询的结果只有1条记录,但是这个查询结果是3条,按正常逻辑来说结果不应该是4条吗?
根据这个结果,顺势分析了IFNULL这个函数,
将IFNULL(item_id, '')这部分替换成结果值试一下
替换成字符串的结果
select inspection_item
where id not in (select '3323211050993319390'
from plan_item
where plan_id = 3323211050993319936)
结果是3条
替换成数值型的试一下
select inspection_item
where id not in (select 3323211050993319390
from plan_item
where plan_id = 3323211050993319936)
结果是4条
说明IFNULL()函数转换的时候也有陷阱,结果是什么类型取决于你第二个参数是数字还是字符串,若第二个类型为字符串,结果也为字符串,与not in连用的时候有大坑。会造成数据不准确,比较的时候是两边都丢失精度再比较的,inspection_item表的多个id会等于同一个字符串id,这就很奇怪了。
经过测试IFNULL(item_id, '')改成IFNULL(item_id, -1)能得到正确结果,not in里不用select,直接写not in ('3323211050993319390')也得到了正确结果。
先记录一下,有时间看看源码怎么处理not in 结果集临时表。