mysql -- 左连接一对多只取一条,去重重复字段
作者:mmseoamin日期:2023-12-21

背景:

        例如,给你一张用户表,还有一张地区信息表(每条数据都是到省 - 市 - 县 的地区信息,具体到县区),用户表中有用户所在市区字段,你要根据 地区信息表 查用户的所在市区的市区编码。就会出现一个情况,用户表 左连接 地区信息表  根据市区信息去匹配,一对多(比如惠州有7的县区),这个时候你只要随机的一条就够不需要多条,现在就考虑如何去重

sql大概如下:

        select  用户表id, 用户字段,市区编码   

        from 用户表

        left join 地区信息表  on  用户市区 = 地区表市区

尝试一:

        使用 DISTINCT

修改sql:

        select  DISTINCT 用户表id, 用户字段,市区编码   

        from 用户表

        left join 地区信息表  on  用户市区 = 地区表市区

结果:

        没用,原因是 mysql的DISTINCT关键字,是后面跟多少个字段,就是多少个字段一起组合,组合后所有字段一样才会去重, 并不是说你在id前面,就会对id字段一样的数据去重(老实说个人觉得这个关键字很鸡肋,查询的所有字段完全一样才去重,基本就是相当于表中有两条一模一样的数据,一般都不可能),由于市区编码不同县区不一样,所以这个关键字根本去不了重

尝试二:

        使用分组 group by

修改sql:

        select  用户表id, 用户字段,市区编码   

        from 用户表

        left join 地区信息表  on  用户市区 = 地区表市区

        group by 用户表id

结果:

        可以实现,因为根据分组后,多条数据的用户id是相同的,分到同一组,所以查询就剩下一条了,这样你取到的市区编码就是随机的一条

        但是,银行mysql后面的版本有个ONLY_FULL_GROUP_BY 这个设置,大概的意思就是,你如果使用group by,那么你的select 的字段必须是group by中的分组字段,或者其他的使用了聚合函数的字段。所以 (select  用户表id, 用户字段,市区编码   ) 是会报错的,只能用 (select  用户表id),或者根据三个字段一起分组(group by  用户表id, 用户字段,市区编码   ),但是又相当于没分组了,而且正常的项目查询的字段何止三个,肯定不能都分组,效率很低,所以也不行,除非你关了上面这个ONLY_FULL_GROUP_BY ,或者使用低版本mysql

尝试三:

        这次是使用子查询的方法,在子查询中使用group by,让子查询里变成一个市区一条数据而不是原来的一个县区一个数据

修改sql:

        select  用户表id, 用户字段,市区编码   

        from 用户表

        left join 

                (select 地区表市区 ,max(市区编码) 

                from 地区信息表

                group by 地区表市区

                ) as d 

                on  用户市区 = d.地区表市区

结果:

        成功,在子查询中,用分组已经得到一个市区一条数据,然后用max聚合函数查到最大的市区编码(相当于随机获取其中一条),这样子查询和用户表的数据就是一对一,就可以实现我们的需要

结语:

        上送需求是我根据我实际工作遇到的举例出来的,相信也有不少朋友遇到相同的,上述仅代表我个人的处理过程和意见,如果朋友们有其他更好的方法也请不吝赐教,谢谢