查找相同单词的重音和非重音变体

时间:2016-06-06 19:30:32

标签: mysql diacritics

我有一个表示人员的数据库表,记录中有人名。一些名称中包含重音字符。有些人没有。有些是重音版的非重音重复。

我需要生成所有潜在重复项的报告,方法是查找除重音符号相同的名称(第一个,中间的,最后一个),以便其他人可以浏览此列表,验证哪些是真正的重复,哪些实际上是不同的人(我假设他们有其他方式知道)。

例如:Jose DISTINCT-LAST-NAMEJosé DISTINCT-LAST-NAME应该被视为潜在的重复项,因为它们具有相同的字符,但其中一个具有重音字符。

如何通过MySQL编写这种类型的查询?

这个问题:How to remove accents in MySQL?不一样。它要求对字符串进行去加重,并且海报已经有第二列数据已被去除重音。此外,该问题的接受答案是设置字符集和整理。我已经设置了字符集和整理。

我正在尝试生成一个报告,该报告在不同的记录中查找除了重音之外相同的字符串。

3 个答案:

答案 0 :(得分:1)

我发现你的问题非常有趣。

根据这篇文章Accents in text searches,使用“喜欢”条件进行一些字符整理调整将解决您的问题。我没有测试过这个解决方案,所以如果它对你有帮助,请回来告诉我们。

这是一个类似的问题:Accent insensitive search query in MySQL, 根据这个,你可以使用类似的东西:

where 'José' like 'Jose' collate utf8_general_ci

答案 1 :(得分:0)

字符编码的祸根

可以在MySQL中使用各种各样的字符集和编码,在处理编码时,了解它们的相关信息非常重要。特别是,仔细看看之间的差异:

  • utf8_unicode_ci
  • utf8_general_ci
  • utf8_unicode_520_ci
  • utf8mb4_general_ci

构建一些字符集以包含尽可能多的可打印字符,以支持更广泛的用途,而其他字符集则构建为系统之间的可移植性和兼容性。特别是,utf8_unicode_ci将大多数重音字符映射到非重音等效字符。或者,您可以使用更具限制性的uft8_ascii_ci。

查看utf8_unicode_ci collation chartWhat's the difference between utf8_general_ci and utf8_unicode_ci

best answer来自类似的问题“How to remove accents in MySQL?

  

如果为列设置了适当的排序规则,则为值   在该字段内将比较等于其非重音等价物   自然。

mysql> SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT 'é' = 'e';
+------------+
| 'é' = 'e' |
+------------+
|          1 |
+------------+
1 row in set (0.05 sec)

如何将此应用于您的情况?

SELECT id, last-name
FROM people
WHERE last-name COLLATE utf8_unicode_ci IN
(
    SELECT last-name
    FROM people
    GROUP BY last-name COLLATE utf8_unicode_ci
    HAVING COUNT(last-name)>1
)

答案 2 :(得分:0)

好吧,我发现了一些似乎有用的东西(真正的查询涉及更多其他领域,但基本相同的想法):

select distinct p1.person_id, p1.first_name, p1.last_name, p2.last_name
from people as p1, people as p2
where binary p1.last_name <> binary p2.last_name
        and p1.last_name = p2.last_name
        and p1.first_name = p2.first_name
order by p1.last_name, p1.first_name, p2.last_name, p2.first_name;

结果如下:

12345    Bob    Jose    José
56789    Bob    José    Jose
...

这是有道理的,因为BobJosé有2条记录,我知道在这种情况下,它是同一个人,但是一条记录缺少重音。

诀窍是在“last_name”字段上进行binary binary比较以及在所有其他字段上进行匹配。通过这种方式,我们可以找到“相等”且不是二元相等的所有内容。这是有效的,因为使用当前字符集/校对(utf8 / utf8_general_ci),JoseJosé相等但不是二进制相等。你可以这样试试:

select 'Jose' = 'José', 'Jose' like 'José', binary 'Jose' = binary 'José';