【问题标题】:Match slightly different records in a field匹配字段中略有不同的记录
【发布时间】:2020-08-19 07:17:09
【问题描述】:

我有下表。我怎样才能在“想要”中获得结果?我会欣赏想法,我愿意接受任何模糊匹配算法

ID Name   
1  Davi  
2  David 
3  DAVID
4  Micheal
5  Michael
6  Oracle
7  Tepper

想要

ID Name mtch_ind  
1  Davi     1
2  David    1
3  DAVID    1
4  Micheal  2
5  Michael  2
6  Oracle   3
7 Tepper    4

TABLE DDL 和记录插入

CREATE TABLE HAVE (
  ID INTEGER,
  Name VARCHAR(10)
);

INSERT INTO data VALUES ('1', 'Davi');
INSERT INTO data VALUES ('2', 'David');
INSERT INTO data VALUES ('3', 'DAVID');
INSERT INTO data VALUES ('4', 'Micheal');
INSERT INTO data VALUES ('5', 'Michael');
INSERT INTO data VALUES ('6', 'Oracle');
INSERT INTO data VALUES ('7', 'Tepper');

【问题讨论】:

  • 你能解释一下为什么 Davi 和 David 的排名一样吗?
  • ID 1,2 和 3 重复“Davi”。当字符串中的任何模式与其他模式匹配时,它们的排名相同。
  • 检查 SOUNDEX(我没有办法检查 PL/SQL)
  • .>> 当字符串中的任何模式与其他模式匹配时,它们的排名相同。 – VN'sCorner 这意味着如果有 D、Da、Dav、Db、Dc、Dab ......所有这些都匹配?
  • @Srinika - 我猜一个模式应该至少有 2 个字母。等待请求者提供指示,因为当前信息有很多歧义。 SOUNDEX 看起来很合理,但需要 PL/SQL。

标签: sql oracle fuzzy-comparison


【解决方案1】:

这是我认为应该有效的算法:

第 1 步:使用 Jaro Winkler 最接近匹配(阈值为 75%)确定最接近的匹配 选择 h1.name h2.name, UTL_MATCH.JARO_WINKLER (h1.name,h2.name) 作为 match_confidence 从有 h1 加入有h2 在 UTL_MATCH.JARO_WINKLER (h1.name,h2.name) > 0.75 - 考虑 75 % 匹配阈值。 enter image description here

第 2 步:选择匹配置信度最大的 h2.name 或相似记录的顶行

例如 [在此输入图片描述][在此输入图片描述]2

第 3 步:对新列执行密集排序操作,最终得到您想要的结果。

希望这可行 注意:关于 SO 的第一篇文章。我目前无法访问预言机。

【讨论】:

  • 谢谢@sampath
【解决方案2】:

虽然这个解决方案有点难看,但我想出了这个方法。仅供参考,最好先将大写的 DAVID 转换为 David。希望有人会发现这很有用或提出更好的解决方案。谢谢

with table1 as (
SELECT ROW_NUMBER() OVER (ORDER BY firstID) as rowno,A.* FROM (
select 
t1.name
,t1.ID
, case when t1.ID>t1.Fid then fid else T1.ID end as FIRSTID 
, case when t1.ID>t1.Fid then T1.id else fID end as SECONDID 
, case when t1.ID>t1.Fid then t1.NAME else t1.FNAME end as FIRSTNAME
, case when t1.ID>t1.Fid then t1.FNAME  else t1.NAME  end as SECONDNAME
, case when count(*) over (partition by id) =1 then 'nodups' else 'dups' end as ID_chk
from (
SELECT h1.NAME,
 h1.ID, 
  h2.id as Fid,
  h2.name as Fname,
SYS.UTL_MATCH.JARO_WINKLER_SIMILARITY(h1.name,h2.name) as match1 
FROM (select 
NAME,
 ID from HAVE)h1 , (
select 
 NAME,
 ID FROM
have)
h2 where SYS.UTL_MATCH.JARO_WINKLER_SIMILARITY((h1.name),(h2.name)) > 75
order by h1.id
)
t1

)A
)
, no_dups as
(
select * from table1 where ID_chk='nodups'
)
,dups as
(
select * from table1 where ID_chk<>'nodups'
)
, dups_stp1 as
(
select * from dups
WHERE FIRSTID <>  SECONDID
)
, dups_stp2 as 
(
select rowno,ID,FIRSTID,SECONDNAME from dups_stp1 
where FIRSTID not in (select SECONDID from dups_stp1)
)

  select t2.ID,t3.NAME,rnk as mtch_ind  from (
select ID,SECONDNAME as NAME, dense_rank() OVER ( ORDER BY SECONDNAME asc)as rnk from (
select distinct ID, FIRSTID, SECONDNAME  from dups_stp2
union all 
select ID, FIRSTID, SECONDNAME  from no_dups
)t1 
)t2
inner join HAVE t3 on t2.ID=t3.ID
;

参考 https://www.decisivedata.net/blog/cleaning-messy-data-sql-part-1-fuzzy-matching-names

【讨论】:

    猜你喜欢
    • 2013-08-23
    • 1970-01-01
    • 2016-03-20
    • 2020-09-27
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多