问题的起因
这个问题源于一个前几天的新开发的任务,原本很简单的需求,只是在原有基础上新增一个字段的展示;看了原来的代码,发现这个需要在原有的sql上新增加两个表的查询;果断使用left join 将数据查出来了;自测通过了直接提测了;昨天晚上快下班的时候,测试提出了一个问题,说搜索单个单个数据的时候出现了重复数据。
问题的排查
既然出现问题了,就排查呗,debugger了代码,发现不是数据转换的问题,发现sql查询后真的会出现重复数据;
然后自己尝试把自己新增的sql删除了,果然重复的数据消失了;看来就是自己新增的数据查询出现的问题;
然后开始根据表去查询,发现没问题呀,但是查询到我使用left join新增的第二张表的时候发现了问题;
一个id对应了两个数据,并不是完整的1:1,而是变成了1:n;
然后我就开始在网上查询这个问题的解决方案,看了很多,基本介绍的都很统一,模板也都是一套,那就是新建一个表;
然后往表里面插入数据,然后自己写一个left join了一个表,然后查询;
就目前网络上的解决方案,
1.使用DISTINCT函数,亲测没效果,至少是在我这边没什么效果;
2.使用group by 进行分组,可能是我使用的不完美,所以还是有问题,还报错,没办法查询;
后来我还特别使用google了一下,发现搜索出来类似的问题很少;也少有解决方案;
问题的解决
就这样我晚上尝试了多种方式没有解决问题就下班了,今天上午继续在网上找解决方案,也没有找到什么特别好的,不过突然看到了有一个人在相似的问题下
说了一个子查询;剩下什么都没说,我觉得还是尝试一下,然后就改了我新增的那段sql不使用left join而是将两个表使用一个left join 然后里面使用子查询,查询数据库后竟然可以,而且很好用;直接就消除了重复数据;
问题的总结
这个问题的主要原因还是因为对于left join的机制并不是完全的理解,其实这个
1.left join 就是以左侧的记录为主根基,右侧的数据有的话就会展示,没有的话就会变成null,是一种比较简便的表关联方式;
2.right join 顾名思义就是已右侧的数据为主根基,左侧的数据有的话就会展示,没有的话就是展示null;
结尾的sql展示
1.之前的查询出重复数据的sql–只放出我新增的sql – 涉及具体的表明就直接简化展示了
LEFT JOIN Test1(NOLOCK) d ON a.ID = d.ID
LEFT JOIN Test2(NOLOCK) e ON d.MIPID = e.MIPID
AND e.Status in (2,5) AND
e.No <> '' and e.No IS NOT NULL
2.更改为子查询之后的正确sql
LEFT JOIN (
SELECT MIO.ID,MIP.Type FROM Test1(NOLOCK) AS MIO,Test2(NOLOCK) AS MIP
WHERE MIO.MIPID = MIP.MIPID
AND MIP.Status in (2,5) AND MIP.No <> ''
AND MIP.No IS NOT NULL
) e ON a.ID = e.ID
更改后只不过将两个表内部的查询方式放在子查询里面,然后与外部的查询还是需要在on里面;
这样就可以消除重复数据了。