我看到关于这个常见问题的堆栈有很多问题和潜在的答案。由于操作员输入错误或其他轻微变化,您有多年来可能吸引了多个重复记录的名称或公司或产品表。
我正在尝试创建后端管理工具来管理此问题。所以它不会是一个高流量的页面,但它仍然不应该杀死构建记录集的数据库。
到目前为止,我有这个查询,需要花费几分钟来处理(太长时间):
SELECT
tab1.id as id1,
tab1.creative as creative1,
tab2.id as id2,
tab2.creative as creative2
FROM
creatives tab1,
creatives tab2
WHERE
SOUNDEX(tab1.creative)= SOUNDEX(tab2.creative)
AND
tab1.id<>tab2.id
AND
tab1.id=(
SELECT
MAX(id)
FROM
creatives tab
WHERE
SOUNDEX(tab.creative)=SOUNDEX(tab1.creative))
现在除了花费太长时间才能返回结果之外,结果有时候太模糊了。例如,它找到了这些很好:
Convenery of Trades of Edinburgh | Convenery of Trades of Edinbubrgh
Crowdedlogic Theatre Company | Crowded Logic Theatre Company
但这些似乎不合时宜
Daniel Cope | Dan Willis & Obie
David Williams | David Holmes
那么,有没有更好的(更快,更不模糊)的方式呢?
答案 0 :(得分:7)
您的问题分为两部分。
首先,为什么你的查询很慢?
其次,SOUNDEX()
为什么会有太多的误报?有没有比SOUNDEX()
提供近似匹配的更好方法?
让我们一次拿起一个。
首先,让我们尝试加快这个查询。让我们从标准SQL中重新编写它(消除旧式JOIN)。
SELECT
tab1.id as id1,
tab1.creative as creative1,
tab2.id as id2,
tab2.creative as creative2
FROM creatives AS tab1
JOIN creatives tab2
ON (
tab1.id < tab2.id /* don't duplicate pairs a/b b/a */
AND SOUNDEX(tab1.creative)= SOUNDEX(tab2.creative)
)
现在让我们省略查询的最后一个句子。
正如您所看到的,如果您的表中有n行,这将按(n平方)次数的顺序评估SOUNDEX函数。
我建议你在表格中添加一个新列。将它设为文本字符串。称之为compare_hash。
然后像这样填充:
UPDATE creatives
SET compare_hash = SOUNDEX(creative)
然后将其编入索引。
然后运行此查询:
SELECT
tab1.id as id1,
tab1.creative as creative1,
tab2.id as id2,
tab2.creative as creative2
FROM creatives AS tab1
JOIN creatives tab2
ON (
tab1.id < tab2.id /* don't duplicate pairs a/b b/a */
AND tab1.compare_hash = tab2.compare_hash
)
这应该快一点,因为它可以使用索引。
关于你的第二个问题。看,这是交易:SOUNDEX()旨在获得大量误报。它也是为美国英语名字设计的。这是一个老式的贝尔系统电话公司信息操作员功能,当人们要求Bessie Schmidt想要Bessie Smith时,它会显示多个名字。
您需要烹饪一些其他比较哈希函数并进行实验。关于你的额外表格列很酷的事情就是你可以这样做。此示例将所有字符串转换为小写,然后拉出空格,然后拉出每个元音。因此,“David Williams”的散列将是“dvdwllms”,这与“dvdhlms”不同
UPDATE creatives SET compare_hash = LOWER(creative);
UPDATE creatives SET compare_hash = REPLACE(compare_hash , ' ', '');
UPDATE creatives SET compare_hash = REPLACE(compare_hash , 'a', '');
UPDATE creatives SET compare_hash = REPLACE(compare_hash , 'e', '');
UPDATE creatives SET compare_hash = REPLACE(compare_hash , 'i', '');
UPDATE creatives SET compare_hash = REPLACE(compare_hash , 'o', '');
UPDATE creatives SET compare_hash = REPLACE(compare_hash , 'u', '');
完成compare_hash之后,您可以运行相同的自连接查询。
(我已经尝试过Levenshein距离。这个问题就是为不同长度的字符串对获得一致的相同度量。)
这需要一些麻烦和一些肘部油脂才能完成这项工作。你在编程中编程了多少取决于http://xkcd.com/1205/