数据业务札记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
结果如下:

可以看到,这个才是没有冗余信息的结果。这才是最后需要的结果。这次札记主要技巧在于使用开窗函数进行
去重,以及构造好一个特殊的分组条件来满足我们的实际需求。



#数据分析师##sql##秋招##春招##校招#
全部评论
感觉挺复杂的啊
点赞 回复 分享
发布于 2022-08-02 17:41

相关推荐

10-25 23:12
门头沟学院 Java
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-26 16:06
已编辑
快手电商 后端 23k-35k
点赞 评论 收藏
分享
评论
1
3
分享
牛客网
牛客企业服务