5

我有来自 2 个不同来源的脏数据。我正在寻找一些关于匹配它们的最佳实践。以下是一些数据示例:

Source1.Name                   Source2.Name
Adda Clevenger Jr Prep School  Adda Clevenger Junior Preparatory School
Alice Fong Yu Alt School       Alice Fong Yu Alternative School
Convent Of Sacred Heart Es     Convent of Sacred Heart Elementary School
Rosa Parks Elementary School   Rosa Parks Elementary School

人类可以看到这 4 个示例应该与理想的模糊匹配匹配。我拥有出色的传统模糊匹配软件,可以捕捉错别字和其他小的变化。但是在这个数据集中,我有大约十几个规则来管理诸如“Preparatory”->“Prep”之类的缩写。我想在查询中捕获所有这些规则。(然后我将分别处理更传统的模糊性。)

是否有众所周知的 SQL 模式来处理此要求?它可以像学习可以在我的搜索中解锁示例的魔术关键字一样简单。这是一种“翻译表”或“缩写表”,但我只是编造了这些术语。我还没有找到被广泛接受的术语。

从概念上讲,我的目标是从这个天真的查询开始:

/* This succeeds for 1 record and fails for 3 in the sample data set above. */
SELECT * FROM ...
WHERE Source1.Name = Source2.Name

然后将其修改为可以获得上面显示的所有所需匹配的内容。我希望我可以使用一些嵌套的 REPLACE 函数来暴力破解它:

/* This works for the 4 samples given */
SELECT * FROM ...
WHERE 
  REPLACE( REPLACE( REPLACE( Source1.Name, 'Preparatory', 'Prep' ), 'Alternative', 'Alt' ), 'Elementary School', 'Es' )
  = REPLACE( REPLACE( REPLACE( Source2.Name, 'Preparatory', 'Prep' ), 'Alternative', 'Alt' ), 'Elementary School', 'Es' )

这感觉不优雅。它越来越难看,因为我解释了不一致的缩写(例如,“International”有时是“Intl”,有时是“Int”“l”)。对于重叠的缩写(例如“小学”->“Es”但在其他情况下“学校”->“学校”),它并不是特别平滑。

其他人是如何解决这个问题的?

注意:我使用的是 Oracle。我可能会使用 REGEXP_REPLACE 而不是 REPLACE。我当然会使用 UPPER(或 LOWER)来避免大小写问题。但这些细节并不是问题的核心。

4

1 回答 1

1

如果您有一组已知的翻译,您可以创建一个捕获这些翻译的函数。然后,您可以在您的表上创建一个虚拟列,该列返回此结果。然后,您可以比较虚拟列,简化查询:

create or replace function abbr_replace ( str varchar2 )  
  return varchar2 deterministic as
begin
  return replace( 
                   replace( 
                         replace( 
                             replace(
                               replace( lower( str ), 'preparatory', 'prep' ), 
                                 'junior', 'jr'),
                             'elementary school', 'es'), 
                         'alternative', 'alt' ), 
                     'elementary school', 'es' 
                 );
end abbr_replace;
/

create table source1 (
  name         varchar2(100),
  replace_name varchar2(100) as ( 
      cast ( abbr_replace ( name ) as varchar2(100) ) 
    )
);

create table source2 (
  name         varchar2(100),
  replace_name varchar2(100) as ( 
      cast ( abbr_replace ( name ) as varchar2(100) ) 
    )
);

insert into source1 (name) values ('Adda Clevenger Jr Prep School');
insert into source1 (name) values ('Alice Fong Yu Alt School');
insert into source1 (name) values ('Convent Of Sacred Heart Es');
insert into source1 (name) values ('Rosa Parks Elementary School');

insert into source2 (name) values ('Adda Clevenger Junior Preparatory School');
insert into source2 (name) values ('Alice Fong Yu Alternative School');
insert into source2 (name) values ('Convent of Sacred Heart Elementary School');
insert into source2 (name) values ('Rosa Parks Elementary School');

commit;

select s1.name, s2.name
from   source1 s1
join   source2 s2
on     s2.replace_name = s1.replace_name;

NAME                                               NAME                                             
-------------------------------------------------- --------------------------------------------------
Adda Clevenger Jr Prep School                      Adda Clevenger Junior Preparatory School          
Alice Fong Yu Alt School                           Alice Fong Yu Alternative School                  
Convent Of Sacred Heart Es                         Convent of Sacred Heart Elementary School         
Rosa Parks Elementary School                       Rosa Parks Elementary School

有几点需要注意:

  • 您必须将函数声明为deterministic
  • 您需要使用 11g 或更高版本才能使用它

如果您正在寻找更一般的模糊匹配,Oracle 已经实现了 Levenshtein Distance 和 Jaro-Winkler 匹配算法。这些在 utl_match 中:

select s1.name, s2.name, utl_match.jaro_winkler(s1.name, s2.name) jw
from   source1 s1
join   source2 s2
on     utl_match.jaro_winkler(s1.name, s2.name) > .9;

NAME                                               NAME                                               JW
-------------------------------------------------- -------------------------------------------------- --
Adda Clevenger Jr Prep School                      Adda Clevenger Junior Preparatory School           0.904
Alice Fong Yu Alt School                           Alice Fong Yu Alternative School                   0.925
Convent Of Sacred Heart Es                         Convent of Sacred Heart Elementary School          0.902
Rosa Parks Elementary School                       Rosa Parks Elementary School                       1.000

LiveSQL上也提供脚本

于 2015-12-22T10:30:45.920 回答