数据业务札记02:表非等值自关联的去重写法
在某些业务场景下,我们需要找到与客户信息相同(号码、地址等)的客户。这时我们很直观的想法是对表进行自关联。
我们本地建表来看一个例子:
由于这里的关联条件是或条件,我们采取等值拆分的方法来进行条件拆解。具体过程和数据业务札记01:https://www.nowcoder.com/discuss/999011类似。
这里我们运行的代码是:
select a.cu_id as id1 ,a.tele as tele1,a.place as place1, b.cu_id as id2 ,b.tele as tele2,b.place as place2 from cust_info1 a left join cust_info1 b on a.tele = b.tele where a.tele = b.tele and a.cu_id!=b.cu_id union all select a.cu_id as id1 ,a.tele as tele1,a.place as place1, b.cu_id as id2 ,b.tele as tele2,b.place as place2 from cust_info1 a left join cust_info1 b on a.place = b.place where a.place = b.place and a.cu_id!=b.cu_id order by id1结果如下:
可以看到,我们的结果中不可避免的出现id为11的客户和id为19的关联起来,id为19的客户也和id为11的客户关联起来。
于是我们需要将冗余的部分清楚,因为在我们看来id11和id19储存的信息是一致的。这里我们可以考虑用开窗函数进行去重。
这里的小技巧是,因为在我们看来id1=11,id2=19和id1=19,id2=11没有差异,因此开窗函数的分组partition by取id1+id2,
直观的意思是id1并id2,其结果相同的纪录归为一组,并按照某一字段进行排序标号。这里我们考虑对phone1进行标号。
具体代码如下:
select * from (select id1,tele1,place1,id2,tele2,place2,row_number ()over(partition by id1+id2 order by tele1) rn1 from (select a.cu_id as id1 ,a.tele as tele1,a.place as place1, b.cu_id as id2 ,b.tele as tele2,b.place as place2 from cust_info1 a left join cust_info1 b on a.tele = b.tele where a.tele = b.tele and a.cu_id!=b.cu_id union all select a.cu_id as id1 ,a.tele as tele1,a.place as place1, b.cu_id as id2 ,b.tele as tele2,b.place as place2 from cust_info1 a left join cust_info1 b on a.place = b.place where a.place = b.place and a.cu_id!=b.cu_id order by id1) c )d where rn1=1
结果如下:
可以看到,这个才是没有冗余信息的结果。这才是最后需要的结果。这次札记主要技巧在于使用开窗函数进行
去重,以及构造好一个特殊的分组条件来满足我们的实际需求。