56

我的用户将通过剪切和粘贴一个包含公司名称的大字符串来导入。

我有一个现有且不断增长的 MYSQL 公司名称数据库,每个数据库都有一个唯一的 company_id。

我希望能够解析字符串并为每个用户输入的公司名称分配一个模糊匹配。

现在,只是做一个直接的字符串匹配,也很慢。** Soundex 索引会更快吗?如何在用户输入时为他们提供一些选项?**

例如,有人写道:

微软 -> 微软
基本要素 -> 基本要素
Polycom, Inc. -> 宝利通

我发现以下似乎与此问题相似的线程,但发帖人尚未批准,我不确定他们的用例是否适用:

如何在大型字符串数据库中找到字符串的最佳模糊匹配

在 Java 中匹配不准确的公司名称

4

9 回答 9

60

您可以从 using 开始SOUNDEX(),这可能会满足您的需要(我想象了一个自动建议框,其中包含用户正在输入的现有替代方案)。

的缺点SOUNDEX()是:

  • 它无法区分较长的字符串。仅考虑前几个字符,最后发散的较长字符串会生成相同的 SOUNDEX 值
  • 第一个字母必须相同,否则您将无法轻松找到匹配项。SQL Server 具有 DIFFERENCE() 函数来告诉您两个 SOUNDEX 值相距多少,但我认为 MySQL 没有内置这种类型。
  • 对于 MySQL,至少根据文档,SOUNDEX 无法用于 unicode 输入

例子:

SELECT SOUNDEX('Microsoft')
SELECT SOUNDEX('Microsift')
SELECT SOUNDEX('Microsift Corporation')
SELECT SOUNDEX('Microsift Subsidary')

/* all of these return 'M262' */

对于更高级的需求,我认为您需要查看两个字符串的Levenshtein 距离(也称为“编辑距离”)并使用阈值。这是更复杂(=更慢)的解决方案,但它允许更大的灵活性。

主要缺点是,您需要两个字符串来计算它们之间的距离。使用 SOUNDEX,您可以将预先计算的 SOUNDEX 存储在您的表中,并对其进行比较/排序/分组/过滤。使用 Levenshtein 距离,您可能会发现“Microsoft”和“Nzcrosoft”之间的差异只有 2,但要得出这个结果还需要更多时间。

无论如何,可以在codejanitor.com 上找到 MySQL 的 Levenshtein 距离函数示例:作为 MySQL 存储函数的 Levenshtein 距离(2007 年 2 月 10 日)

于 2008-12-15T21:56:17.580 回答
24

SOUNDEX 是一个很好的算法,但最近在这个主题上取得了进展。创建了另一种称为 Metaphone 的算法,后来将其修改为双 Metaphone 算法。我个人使用了双变音器的 java apache commons 实现,它是可定制的和准确的。

他们在维基百科页面上也有许多其他语言的实现。这个问题已经得到解答,但是如果您发现任何已识别的 SOUNDEX 问题出现在您的应用程序中,很高兴知道有选项。有时它可以为两个完全不同的单词生成相同的代码。创建了双变音位来帮助解决这个问题。

从维基百科窃取:http ://en.wikipedia.org/wiki/Soundex

作为对 Soundex 算法缺陷的回应,Lawrence Philips 出于同样的目的开发了 Metaphone 算法。飞利浦后来对 Metaphone 进行了改进,他称之为 Double-Metaphone。Double-Metaphone 包含比其前身更大的编码规则集,处理非拉丁字符的子集,并返回主要和次要编码以解释英语中单个单词的不同发音。

在双变音位页面的底部,他们有各种编程语言的实现:http ://en.wikipedia.org/wiki/Double-Metaphone

Python & MySQL 实现:https ://github.com/AtomBoy/double-metaphone

于 2008-12-18T23:07:49.103 回答
11

首先,我想补充一点,在使用任何形式的语音/模糊匹配算法时都应该非常小心,因为这种逻辑正是如此,模糊或更简单地说;可能不准确。用于匹配公司名称时尤其如此。

一个好的方法是从其他数据中寻求佐证,例如地址信息、邮政编码、电话号码、地理坐标等。这将有助于确认您的数据被准确匹配的可能性。

有很多与 B2B 数据匹配相关的问题需要在这里解决,我在我的博客(也是更新的文章)中写了更多关于公司名称匹配的内容,但总的来说,关键问题是:

  • 查看整个字符串是没有帮助的,因为公司名称中最重要的部分不一定位于公司名称的开头。即“Proctor and Gamble Company”或“United States Federal Reserve”</li>
  • 缩写在公司名称中很常见,例如 HP、GM、GE、P&G、D&B 等。
  • 一些公司故意将其名称拼写错误,作为其品牌的一部分,并将自己与其他公司区分开来。

匹配精确数据很容易,但匹配非精确数据可能会花费更多时间,我建议您应该考虑如何验证非精确匹配以确保这些匹配具有可接受的质量。

在我们建立 Match2Lists.com 之前,我们曾经花费大量时间来验证模糊匹配。在 Match2Lists 中,我们集成了一个强大的可视化工具,使我们能够查看非精确匹配,这在匹配验证方面被证明是一个真正的游戏规则改变者,降低了我们的成本并使我们能够更快地交付结果。

祝你好运!!

于 2012-08-17T16:13:47.293 回答
4

这是mysql 和 php中 soundex 函数的 php 讨论的链接。我将从那里开始,然后扩展到您的其他定义不那么明确的要求。

您的参考引用了 Levenshtein 匹配方法。两个问题。1.更适合测量两个已知单词之间的差异,而不是搜索。2. 它讨论了一种解决方案,旨在更多地检测校对错误(使用“Levenshtien”作为“Levenshtein”)而不是拼写错误(用户不知道如何拼写,说“Levenshtein”并输入“Levinstein” . 我通常将它与在书中查找短语而不是在数据库中查找键值联系起来。

编辑:回应评论 -

  1. 您至少可以让用户将公司名称放入多个文本框中吗?2. 或使用明确的名称分隔符(比如反斜杠);3. 省略冠词(“The”)和通用缩写(或者您可以过滤这些);4. 挤出空格并与之匹配(所以微软 => microsoft,Bare Essentials => bareessentials);5.过滤掉标点符号;6. 对单词进行“OR”搜索(“bare”或“essentials”)——人们有时会不可避免地忽略其中一个。

疯狂地测试并使用来自用户的反馈循环。

于 2008-12-15T21:28:29.510 回答
1

这个答案导致使用 2 或 3 个字符或更多字符的输入对几乎任何实体进行索引查找。

基本上,创建一个包含 2 列、word 和 key 的新表。在包含要模糊搜索的列的原始表上运行一个进程。此过程将从原始列中提取每个单独的单词,并将这些单词与原始键一起写入单词表。在此过程中,应丢弃经常出现的单词,例如“the”、“and”等。

然后我们在单词表上创建几个索引,如下...

  • word + key 上的普通小写索引
  • 第 2 到第 5 个字符的索引 + 键
  • 第 3 到第 6 个字符的索引 + 键

    或者,在 word 列上创建 SOUNDEX() 索引。

一旦这到位,我们接受任何用户输入并使用普通 word = input 或 LIKE input% 进行搜索。我们从不执行 LIKE %input,因为我们总是在前 3 个字符中的任何一个上寻找匹配项,这些字符都已编入索引。

如果您的原始表很大,您可以按字母表对单词表进行分区,以确保立即将用户的输入缩小到候选行。

于 2018-05-31T16:15:00.050 回答
1

虽然问题询问如何在 MySQL 中进行模糊搜索,但我建议考虑使用单独的模糊搜索(又名容错)引擎来完成此操作。以下是一些需要考虑的搜索引擎:

  • ElasticSearch(开源,功能丰富,操作复杂)
  • Algolia(专有,但有很棒的文档并且超级容易启动和运行)
  • Typesense(开源,提供与 Algolia 相同的模糊搜索功能)
于 2021-02-18T05:29:17.017 回答
0

模糊匹配的最佳函数是 levenshtein。它传统上被拼写检查器使用,所以这可能是要走的路。这里有一个 UDF:http: //joshdrew.com/

使用 levenshtein 的缺点是它不能很好地扩展。一个更好的主意可能是将整个表转储到拼写检查器自定义字典文件中,并从您的应用程序层而不是数据库层执行建议。

于 2008-12-19T16:35:29.750 回答
0

在使用服务器端的受信任且经过良好测试的拼写检查库进行查询之前检查它是否拼写错误,然后对原始文本和第一个建议的正确拼写进行简单查询(如果拼写检查确定它拼写错误)。

您可以为任何值得使用的拼写检查库创建自定义词典,您可能需要这样做以匹配更晦涩的公司名称。

匹配两个简单的字符串比对整个表进行 Levenshtein 距离计算要快得多。MySQL 不太适合这种情况。

我最近解决了一个类似的问题,浪费了很多时间摆弄算法,所以我真的希望有更多的人警告不要在 MySQL 中这样做。

于 2021-08-02T18:27:34.500 回答
0

之前可能有人建议过,但为什么不将数据转储到 Excel 并使用 Fuzzy Match Excel 插件。这将给出从 0 到 1 的分数(1 为 100%)。

我为保存在数据库中的业务合作伙伴(公司)数据执行此操作。下载最新的 UK Companies House 数据并以此为依据进行评分。

对于 ROW 数据,它更复杂,因为我们必须进行更多手动处理。

于 2021-08-17T09:57:06.277 回答