我不知道有比这更好的(本地)方法SOUNDEX()
。它慢的原因是因为它是一个函数,因此需要处理所有记录以计算值并从那里开始工作。解决这个问题的方法是将结果直接存储到表中。我对 MySQL 中的这些功能没有经验,但根据文档 http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#operator_sounds-like看来你可以转换你的WHERE
条款进入
[...] AND SOUNDEX(p.first_name) = SOUNDEX(contacts.first_name) [...]
因此,如果您已经预先计算了这些值(并建立了索引!),则搜索匹配记录的速度应该会快得多!
这就是说我很难弄清楚你的问题。我认为你不需要HAVING COUNT(*) > 1
即便如此,我还是对你想如何对联系人进行分组/过滤感到困惑!?
你想要这样的东西吗:
SELECT c1.id as contact_id,
c2.id as similar_id
FROM contacts c1
JOIN contacts c2
ON c2.id <> c1.id
AND c2.deleted = 0
AND SOUNDEX(c2.first_name) = SOUNDEX(c1.first_name)
AND SOUNDEX(c2.last_name) = SOUNDEX(c1.last_name)
WHERE c1.deleted = 0
ORDER BY c1.date_entered DESC
然后您可以按照上面的建议进行优化
SELECT c1.id as contact_id,
c2.id as similar_id
FROM contacts c1
JOIN contacts c2
ON c2.id <> c1.id
AND c2.deleted = 0
AND c2.first_name_soundex = c1.first_name_soundex
AND c2.last_name_soundex = c1.last_name_soundex
WHERE c1.deleted = 0
ORDER BY c1.date_entered DESC
其中first_name_soundex 保存SOUNDEX(first_name) 等的结果。
建立索引时,您可能希望覆盖索引deleted
, first_name_soundex
, last_name_soundex
。
(据我所知 MySQL 还不支持过滤索引,否则你可以将索引限制为deleted = 0
only).