现实工作中,有一些场景需要关联,然而却不能直接进行关联,因为关联键并不直接存在,只有经过处理后才可以进行关联,今天,我们通过一个例子来学习一下。
需求背景假设有通过笔试的候选人名单如下:
pid
name
1
张三
2
李四
3
王五
4
赵六
经过面试、体检及背调等复核工作,发现部分成员存在问题,不能正常入取,示例数据如下:
check_type
names
health
张三、赵六
age
李四
现在要求筛查出符合所有考核要求的候选人名单。
解决思路要求从通过笔试的候选人名单中,剔除复核过程中不达标的人员。难点在于候选人名单和复核情况名单关键字段结构不一致,候选人的姓名是独立的,而复核表中的姓名是拼接在一起的。
具体到解决思路,有以下几种可以参考:
1、以复核表为基础,把拼接的姓名拆分到行,然后再关联
2、通过正则匹配来关联
3、通过模糊匹配来关联
4、LISTAGG 拼接所有姓名,使用 INSTR 来剔除不达标人员
方法一:拆分到行首先,将复核表中拼接的姓名拆分到行
select check_type, regexp_split_to_table(cnames, '、') cnamefrom t2;查询结果:
check_type
cname
health
张三
health
赵六
age
李四
将候选人表与拆分到行的复核表进行关联
select a.cname from t1 aleft join (select check_type, regexp_split_to_table(cnames, '、') cname from t2) bon a.cname = b.cnamewhere b.cname is null;查询结果:
cname
王五
方法二:正则匹配首先,将候选人表与复核表进行模糊关联,查找在复核表中出现过的候选人
select t1.cname from t1 join t2 on regexp_matches(t2.cnames,concat(t1.cname, '.*'));查询结果:
cname
张三
赵六
李四
剔除复核表中出现的候选人
select cnamefrom t1where cname not in ( select t1.cname from t1 join t2 on regexp_matches(t2.cnames,concat(t1.cname, '.*')) );查询结果:
cname
王五
方法三:模糊匹配使用模糊匹配 + NOT EXISTS 语法
select cname from t1 a where not exists (select cnames from t2 b where b.cnames like '%'||a.cname||'%');查询结果:
cname
王五
方法四:listagg + instr首先使用 listagg 拼接复核表中所有姓名
select listagg(cnames,'、') AS x from t2;查询结果:
x
张三、赵六、李四
使用 INSTR 剔除在复核表中出现的候选人
with a as (select listagg(cnames,'、') AS x from t2)select cname from t1, awhere instr(a.x, cname) = 0;查询结果:
cname
王五
至此,四种方法全部介绍完了,你最喜欢哪一种呢?