用于几乎相似值搜索的算法

时间:2010-07-08 07:04:40

标签: sql sql-server algorithm string-comparison

我在 SQL Server 2008 中有Persons个表。

我的目标是找到地址几乎相似的人。

地址用列statetownstreethouseapartmentpostcodephone来描述

由于某些州(非美国)和人为因素(地址错误等)存在某些特定差异,因此地址不会以相同的模式填充。

地址中最常见的错误

  1. 区分大小写
  2. 有人写了“apt。”,另一个是“公寓”或“ap”。 (虽然地址不是用英文写的)
  3. 空格,圆点,逗号
  4. 写街道名称的差异,比如'博士Jones str。“或”琼斯医生街“或”D。乔恩。 st。“或”Dr Jones st“等。
  5. 主要问题是数据不是相同的模式,因此找到类似的地址真的很困难。

    这种问题有什么算法吗?

    提前致谢。

    更新

    1. 正如我所提到的,地址分为不同的列。我应该生成字符串连接列还是为每列执行步骤? 我假设我不应该连接列,但如果我将单独比较列,我应该如何组织它?我是否应该找到每个列的相似性,将它们联合起来或相交或其他什么?
    2. 我应该收集一些统计数据还是某种教育算法?

15 个答案:

答案 0 :(得分:7)

建议接近它:

  1. 从各个条目创建单词级n-gram(三元组/ 4克可能会这样做)

  2. 对字符串比较进行多次x比较,并按字符串距离对它们进行聚类。有人建议Levenshtein;对于这种任务有更好的选择,Jaro-Winkler Distance和Smith-Waterman工作得更好。像SimMetrics这样的图书馆会让生活变得更轻松

  3. 一旦你有了n-gram的集群,就可以使用成分图来解析整个字符串,即D.Jones St => Davy Jones St. => DJones St.

  4. 不应该太难,这是一个非常普遍的问题。

    更新:根据您的更新,以下是建议的步骤

    1. 将列连接成一个字符串,也许创建一个数据库“视图”。例如,

      创建视图vwAddress 如  选择前10000名     州城,街道,房子,公寓,邮政编码,     州+镇+街道+房屋+公寓+邮政编码为地址  来自......

    2. 编写一个单独的应用程序(比如在Java或C#/ VB.NET中)并使用像JaroWinkler这样的算法来估计组合地址的字符串距离,以创建多个x很多比较。并写入一个单独的表 地址1 |地址n |相似性

    3. 您可以使用Simmetrics来获得相似性:

       JaroWinnkler objJw = new JaroWinkler()
      double sim =  objJw.GetSimilarity (address1, addres n);
      
      1. 你也可以拼错它,以便“1 Jones Street,Sometown,SomeCountry”这样的地址变成“1 Jones Street”,“Jones Street Sometown”等等...... 并比较三卦。 (甚至4克)以获得更高的准确度。

      2. 最后,您可以按相似性排序,以获得最相似地址的群集,并确定适当的阈值。不确定为什么你被卡住了

答案 1 :(得分:5)

我会尝试执行以下操作:

  • 用多个单词分割地址,同时摆脱标点符号
  • 检查所有单词是否通常以不同的方式书写,并用通用名称替换它们(例如替换公寓,ap。,...通过apt,替换Dr.博士,...)
  • 将所有单词按字母顺序排列在一个字符串中
  • 使用模糊字符串比较算法比较所有地址,例如的Levenshtein
  • 调整Levenshtein算法的参数(例如,您希望在更长的字符串上允许更多差异)
  • 最后对字符串进行手动检查

当然,保持数据“正常”的解决方案是为数据库中的每个特征提供显式字段。否则,你将每隔几个月做一次这个练习。

答案 2 :(得分:2)

我在这里看到的主要问题是准确定义相等性。 即使有人写乔恩。和另一个人。 - 你永远无法说出它们是否相同。 (Jon-Jonethan,Joneson,Jonedoe等等;)

我在一家公司工作,我们必须处理这个问题 - 我担心我必须告诉你这种检查导航系统的地址列表是在大多数情况下“手动”完成的。缩写词有时会依赖于语境,还有其他一些因素会使其变得困难。 Ofc替换字符串等是用python完成的 - 但是告诉你这样一个abbr的含义。只能在少数情况下通过脚本完成。 (“圣” - >可以是“圣”和“街”。如何决定?不可能......这是人类的工作。)。

另一个大问题是,你说“有街道”的DJ“还是一个人?或者两者兼而有之?这里有哪一个?这个DJ与琼斯博士相同还是和唐·琼斯一样?无法决定!

你可以在这里用另一个答案提供的列表做一些工作 - 但它会给你足够的“误报”左右。

答案 3 :(得分:2)

您有邮政编码字段!!!

那么,为什么不为您所在的国家/地区购买邮政编码表 并用它来清理您的街道/城镇/地区/省份信息?

答案 4 :(得分:2)

我在上个世纪做了这样一个项目。基本上,合并后合并了两个客户文件,并涉及三个不同来源的名称和地址。

首先,正如许多海报所建议的那样,将所有常用词汇,短语和拼写错误转换为常用形式“Apt”。 “Apatment”等“Apt”。

然后查看名称并识别名字的第一个字母加上第一个姓氏。 (不是那么容易考虑“医学博士亨利德巴斯克维尔史密斯爵士”)但不要担心哪里有歧义只需要两者兼顾!所以,如果幸运的话,你会得到HBASKERVILLE和HSMYTHE。现在摆脱大多数拼写变化发生的所有元音,现在你有HBSKRVLL HSMTH。

你也可以从“H. Baskerville”,“Sir Henry Baskerville Smith”和不幸的“Harold Smith”获得这些字符串,但我们在这里谈论模糊匹配!

在街道,公寓和邮政编码字段上进行类似的练习。但是不要丢掉原始数据!

现在,您首先要比较每个原始字符串并为每个完全匹配的字符串说50分。然后通过你的“标准化”字符串,并为每个完全匹配的字符串说20分。然后浏览所有字符串,并为每个四个字符或更多共同的子字符串说5分。对于每一对比较,你会得到一些得分> 150你可以认为是一定的匹配,有些得分少于50你可以认为不匹配,有些在中间有一些匹配的概率。

你需要做一些调整来改善这一点,方法是添加各种规则,例如“为'smith'的姓减去20分”。你真的必须继续跑步和调整,直到你对得到的比赛感到满意,但是,一旦你看到结果,你会得到一个很好的感觉,哪个得分考虑“匹配”,哪些是你需要摆脱的误报的。

答案 5 :(得分:1)

我认为数据量可能会影响哪种方法最适合您 在从各种艺术家的编辑专辑中索引音乐时,我遇到了类似的问题。有时艺术家是第一位的,有时是歌曲名称,有各种分隔符样式。

我所做的是计算具有相同值的其他条目上出现的次数,以进行有根据的猜测,即歌曲名称或艺术家。

也许您可以使用soundex或类似的算法来查找相似的内容。

编辑:(也许我应该澄清一下,我认为艺术家的名字更可能比歌曲名称更频繁地重复出现。)

答案 6 :(得分:1)

您在评论中提到的一件重要事情是,您将以交互方式进行此操作。

这允许解析用户输入,同时验证任何缩写的猜测并纠正很多错误(例如电话号码输入的方​​式适用于某些联系人管理系统 - 系统尽最大努力解析和更正国家代码,区号和数字,但最终会向用户显示猜测并有机会更正输入)

如果你想做得非常好,那么保留邮政编码,城镇,街道,缩写及其变体的数据库/词典可以改善数据验证和预处理。

所以,至少你会有完全合格的地址。如果您可以对所有输入执行此操作,您将对所有数据进行分类,然后匹配可以在某些字段上严格,而在其他字段上则不那么严格,匹配分数根据您指定的权重计算。

在您始终对输入进行预处理之后,n-gram应该能够找到类似的地址。

答案 7 :(得分:1)

您是否考虑过SQL Server Integration Services?模糊查找组件允许您查找“近似匹配”:http://msdn.microsoft.com/en-us/library/ms137786.aspx

对于新输入,您可以从.Net代码调用包,传递要作为一组参数检查的值行,您可能需要为此保持令牌索引,以便足够快以便用户进行交互

这里有一个地址匹配的示例:http://msdn.microsoft.com/en-us/magazine/cc163731.aspx

答案 8 :(得分:1)

我假设响应时间并不重要,问题是在数据库中找到现有地址,而不是合并重复项。我还假设数据库包含大量地址(比如300万),而不是可以手工或Amazon's Mechanical Turk经济地清理的数字。

预先计算 - 识别信息含量高的地址片段。

  1. 识别每个数据库字段中使用的所有唯一字词并计算其出现次数。
  2. 消除非常常见的单词和缩写。 (Street,st。,appt,apt等)
  3. 显示输入地址时

    1. 为包含这些字词的现有地址确定最独特的字词并搜索(街道LIKE'%Jones%')。
    2. 使用预先计算的统计信息来估算结果集中的地址数
    3. 如果估算结果设置太大,请选择第二个唯一的单词并将其合并到搜索中(Street LIKE'%Jones%'和Town LIKE'%Anytown%')
    4. 如果估算的结果设置太小,请选择第二个唯一的单词并将其合并到搜索中(Street LIKE'%Aardvark%'或Town LIKE'%Anytown')
    5. 如果实际结果集太大/太小,请重复查询,像以前一样添加更多字词。
    6. 这个想法是在地址中找到具有高信息内容的足够片段,可以搜索以提供合理数量的替代品,而不是找到最佳匹配。为了更加容忍拼写错误,可以使用三元组,四元组或soundex代码代替单词。

      显然,如果您有实际州/城镇/街道的列表,那么可以在数据库和搜索地址中进行一些数据清理。 (我很惊讶Armenian postal service没有提供这样的清单,但我知道有些邮政服务会收取过多的信息。)

      实际上,我看到的大多数系统都试图通过电话号码查询人们的账号:显然这是否是一个实际的解决方案取决于数据的性质及其准确性。

      (还要考虑横向思维方法:你能找到一个邮件订单邮件列表经纪公司,它会为你清理你的数据库吗?他们甚至愿意付钱给你使用这些地址。)

答案 9 :(得分:1)

我发现了一篇很棒的文章。

添加一些dll作为 sql用户定义函数我们可以使用 SimMetrics 库来使用字符串比较算法。

检查

http://anastasiosyal.com/archive/2009/01/11/18.aspx

答案 10 :(得分:0)

这种变化的可能性是无数的,即使存在这样的算法,它也永远不会是万无一失的。你毕竟不能有名词的拼写检查。 您可以做的是提供先前输入的字段值的下拉列表,以便他们可以选择一个,如果已存在特定名称。 最好为公寓等每个值设置单独的字段。

答案 11 :(得分:0)

你可以把所有地址都扔到谷歌地图这样的网络服务上(我不知道这个地址是否合适),看看他们是否提供了相同的GPS坐标。

答案 12 :(得分:0)

的可能性是在数据库中有一个字典表,它将所有变体映射到该单词的“正确”版本:

*Value* | *Meaning*
Apt.    | Apartment
Ap.     | Apartment
St.     | Street

然后在比较之前通过字典运行每个单词。

编辑:此单独太天真,不实用(请参阅评论)。

答案 13 :(得分:0)

另一个想法是使用学习。例如,您可以了解每个缩写及其在句子中的位置,缩写的含义。

3 Jane Dr. -> Dr (in 3rd position (or last)) means Drive
Dr. Jones St -> Dr (in 1st position) means Doctor
例如,您可以使用决策树并让用户训练系统。可能每次使用的例子都很少就足够了。你不会将D.Jones这样的单字母缩写分类为大卫琼斯或琼斯博士。但是在翻译完第一级后,你可以查看城镇的街道索引,看看你是否可以将D.扩展为街道名称。

同样,在存储之前,您将通过决策树运行每个地址。​​

感觉应该有一些商业产品在那里做到这一点。

答案 14 :(得分:0)

一种方法可以是将Levenshtein distance算法应用于地址字段。这将允许您比较字符串的相似性。

修改 在查看了您正在处理的地址差异之后,这可能没有任何帮助。