Sql Oracle中如何利用模糊匹配实现精确连接

Sql Oracle中如何利用模糊匹配实现精确连接,sql,oracle,fuzzy-comparison,jaro-winkler,Sql,Oracle,Fuzzy Comparison,Jaro Winkler,我正在尝试将一个表中的一组县名称与另一个表中的县名称连接起来。这里的问题是,两个表中的县名称都没有标准化。它们在数量上不一样;此外,它们可能不会总是以类似的模式出现。例如,表A中的县“圣约翰”可以表示为表B中的“圣约翰”。我们无法预测它们的共同模式 这意味着,我们不能在连接时使用等于=条件。所以,我尝试使用oracle中的JARO_WINKLER_相似性函数来加入它们。 我的左外连接条件如下: Table_A.State = Table_B.State AND UTL_MATCH.JARO_W

我正在尝试将一个表中的一组县名称与另一个表中的县名称连接起来。这里的问题是,两个表中的县名称都没有标准化。它们在数量上不一样;此外,它们可能不会总是以类似的模式出现。例如,表A中的县“圣约翰”可以表示为表B中的“圣约翰”。我们无法预测它们的共同模式

这意味着,我们不能在连接时使用等于=条件。所以,我尝试使用oracle中的JARO_WINKLER_相似性函数来加入它们。 我的左外连接条件如下:

Table_A.State = Table_B.State 
AND UTL_MATCH.JARO_WINKLER_SIMILARITY(Table_A.County_Name,Table_B.County_Name)>=80
在对结果进行了一些测试之后,我给出了80分,这似乎是最优的。 这里的问题是,我加入时会出现一系列的误报。例如,如果在同一个州(例如巴里州和贝州)下有一些名称相似的县,那么如果度量值>=80,它们将被匹配。 这会创建不准确的关联数据集。 有人能提出一些建议吗

谢谢, 达夫

您能帮我建立一个查询,为表B/C/D中的每个记录查找表a,并与a中的县名称进行匹配,该县名称的相似度最高,即>=80吗

Oracle安装程序:

查询:

输出:


使用一些编好的测试数据内联,您可以使用自己的表A和表B代替前两个with子句,并从匹配项开始,如下所示:

结果:

STATE COUNTY_NAME MATCHED_NAME      SCORE
----- ----------- ------------ ----------
A     BARRY       BARRY               100
A     ST JOHNS    SAINT JOHNS          80
B     CHEESECAKE  CHEESE               92
B     WAFFLES     WAFFLING             86
C     UMBRELLAS   UMBRELLAS           100
其思想是matches计算所有分数,ranked_matches在state、county_name中为其分配一个序列,最终查询将挑选所有得分最高的人,即排名过滤器=1


您可能仍然会得到一些重复项,因为无法阻止两个不同的模糊匹配获得相同的分数。

也许您创建了一个包含已知误报的表,并使用a和表a.State、表a.County、表B.County不在选择状态,a、B来自已知误报检查?另一种可能是用您自己的实现来取代JARO_WINKLER_相似度,该实现具有所有必要的魔力…感谢您的评论。问题是我们需要检查每一条记录以了解误报。刚才我发现蒙哥马利与梦露在同一州的比赛分数为84。达到目标的另一种方法是先使用标准化函数,例如,用“ST”替换“SAINT”,然后使用JARO_WINKLER_相似度更高的阈值。如果过滤只保留排名最高的80以上的比赛,会发生什么对于表A中的每一行?那么结果有用吗?您是否也尝试过添加每个县的SOUNDEX值的比较。例如,梦露/蒙哥马利在84岁时比赛,但SOUNDEX不同。本质上,你的问题是你想要一个精确的匹配,使用“模糊”算法,这不可能总是有那个准确性。该死,MTO比我快。我试图避免使用额外的嵌套级别重复JWS函数,但我不知道这是否会在实践中对性能产生任何影响。
SELECT *
FROM   (
  SELECT wtm.word,
         ow.word AS official_word,
         UTL_MATCH.JARO_WINKLER_SIMILARITY( wtm.word, ow.word ) AS similarity,
         ROW_NUMBER() OVER ( PARTITION BY wtm.word ORDER BY UTL_MATCH.JARO_WINKLER_SIMILARITY( wtm.word, ow.word ) DESC ) AS rn
  FROM   words_to_match wtm
         INNER JOIN
         official_words ow
         ON ( UTL_MATCH.JARO_WINKLER_SIMILARITY( wtm.word, ow.word )>=80 )
)
WHERE rn = 1;
WORD           OFFICIAL_WO SIMILARITY         RN
-------------- ----------- ---------- ----------
MONROE ST      MONROE              93          1
MONTGOMERY BAY MONTGOMERY          94          1
SAINT JOHN     SAINT JOHNS         98          1
ST JAMES       SAINT JAMES         80          1
with table_a (state, county_name) as
     ( select 'A', 'ST JOHNS' from dual union all
       select 'A', 'BARRY' from dual union all
       select 'B', 'CHEESECAKE' from dual union all
       select 'B', 'WAFFLES' from dual union all
       select 'C', 'UMBRELLAS' from dual )
   , table_b (state, county_name) as
     ( select 'A', 'SAINT JOHNS' from dual union all
       select 'A', 'SAINT JOANS' from dual union all
       select 'A', 'BARRY' from dual union all
       select 'A', 'BARRIERS' from dual union all
       select 'A', 'BANANA' from dual union all
       select 'A', 'BANOFFEE' from dual union all
       select 'B', 'CHEESE' from dual union all
       select 'B', 'CHIPS' from dual union all
       select 'B', 'CHICKENS' from dual union all
       select 'B', 'WAFFLING' from dual union all
       select 'B', 'KITTENS' from dual union all
       select 'C', 'PUPPIES' from dual union all
       select 'C', 'UMBRIA' from dual union all
       select 'C', 'UMBRELLAS' from dual )
   , matches as
     ( select a.state, a.county_name, b.county_name as matched_name
            , utl_match.jaro_winkler_similarity(a.county_name,b.county_name) as score
       from   table_a a
              join table_b b on b.state = a.state  )
   , ranked_matches as
     ( select m.*
            , rank() over (partition by m.state, m.county_name order by m.score desc) as ranking
       from   matches m
       where  score > 50 )
select rm.state, rm.county_name, rm. matched_name, rm.score
from   ranked_matches rm
where  ranking = 1
order by 1,2;
STATE COUNTY_NAME MATCHED_NAME      SCORE
----- ----------- ------------ ----------
A     BARRY       BARRY               100
A     ST JOHNS    SAINT JOHNS          80
B     CHEESECAKE  CHEESE               92
B     WAFFLES     WAFFLING             86
C     UMBRELLAS   UMBRELLAS           100