如何在 MySQL table 中找到搜索字符串的所有变体(重音等)?
How to find all variations (accented, etc) of a searched string in MySQL table?
我有一个很大的 MySQL
、InnoDB
table,它在 utf8mb4_unicode_ci
中保存数据。我有几乎所有基于拉丁字母的语言的记录。我可以轻松地搜索带有重音字符的单词并找到具有不同变体的结果 (accented/not-accented),但土耳其语存在问题。当您指定包含大 I
字母的单词时,基本 LIKE
关键字在 SQL
行中不起作用。我希望看到所有包含该字母小写版本的单词(无点 i
)。
因此,I
在英语中是 i
,但在土耳其语中是 dotless i
。 (ı
)
SELECT * FROM words WHERE word LIKE 'SIR'
字不带sır
字。它只带来 sir
个词,但它们都存在于同一个 table.
你遇到过这样的问题吗? SQL
如何解决?
更新:
SELECT * FROM words WHERE word LIKE 'SIR'
COLLATE utf8mb4_turkish_ci
returns sır
但不是 sir
。尽管这可以解决一些问题,但不幸的是,从这个查询到 return 需要 23 秒而不是 0.00003 秒(没有 COLLATE
关键字)
这是一般 unicode 文本处理的已知棘手问题。您所能做的就是对具有不同形式 i 的单词使用 OR
或使用正则表达式模式。
索引还是扫描?
在您的示例中,我假设 word
已编入索引? table 相当大?在这种情况下,索引对于查找匹配 指定排序规则 的行非常有用。任何其他排序规则(您使用 COLLATE ...
的情况)需要忽略索引并扫描 整个 table(慢)。
使用 REGEXP
将 也 需要完整的 table 扫描。
即时执行 REPLACE(...)
需要完整的 table 扫描。
因此,假设有 "too many" 行可以进行完整的 table 扫描,没有简单的方法可以搜索 sır
或 sir
任意归类。让我们寻找另一种方式...
首先,让我们看一些整理案例。
在大多数 utf8 归类中,包括 utf8_unicode_ci,I=i=Ì=Í=Í=È=Ï=ì=í=í=î=ï=Ī=ī=Ç=į=İ
在 utf8_turkish_ci 中,I=ı,但它们出现在 i=Ì=Í=Í=È=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ 之前(因此,解释了你的部分问题)。
大多数其他 utf8 归类将 ı 视为介于 i 和 j 之间。
utf8_general_ci 略有不同:I=i=Ì=Í=Í=È=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ=ı
utf8_icelandic_ci 将一些带重音符号的 i 视为不同的字母:I=i=Ì=È=Ï=ì=î=ï=Ī=ī=Į=į=İ,但 Í=Í=í=í 介于两者之间I 和 J。那个人也在 Z 之后对这些进行排序: Ä=Æ=ä=æ Ö=Ø=ö=ø Å=å
见我的Reference
另一个问题:重音字母 可以 显示为两个 utf8 字符 - 字母,然后是 "non-spacing mark"
那么,怎么办??
计划 A:构建您自己的归类。这需要一些工作,但并非不可能。这将是最佳的,为您提供最佳性能。正如我们将在下面看到的,utf8_unicode_520_ci 非常接近,可以作为一个起点。
计划 B:在您的 table 中添加另一列;我们称它为 wordx
。它会有 word
,但会去除高重音。然后索引 wordx
而不是 word
。所以 word='sır' 的行会有 wordx='sir'.
计划 C:使用上面讨论的等效项,如果 "I" 从每个组中选择一种类型用于 table 中定义的排序规则,然后使用utf8_unicode_520_ci
与 UNION
:
( SELECT ... WHERE word = 'sir' )
UNION ALL
( SELECT ... WHERE word = 'sır' )
这应该包含 i
的所有风格。
哎呀,如果单词有多个不同的口音table字母怎么办?乍一看,这可能不是问题——所有 a
在 utf8_unicode_520_ci 中整理相等。浏览其余的字母,除了 ı
出现问题外,我没有看到任何其他内容。
下面是 utf8_unicode_520_ci
的有趣 等价物:
A=a=ª=À=Á=Á=Â=Ã=Ä=Å=à=á=á=â=ã=ä=å=Ā=ā=Ą=ą Aa ae=Æ=æ az B=b C=c=Ç=ç=Č=č ch cz
D=d=Ð=ð=Ď=ď dz E=e=È=É=É=Ê=Ë=è=é=é=ê=ë=Ē=ē=Ĕ=ĕ=Ė=ė=Ę=ę=Ě=ě F=f fz ƒ
G=g=Ğ=ğ=Ģ=ģ gz H=h hz I=i=Ì=Í=Í=Î=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ ij=ij iz ı J=j
K=k=Ķ=ķ L=l=Ĺ=ĺ=Ļ=ļ=Ł=ł lj=LJ=Lj=lj ll lz M=m N=n=Ñ=ñ=Ń=ń=Ņ=ņ=Ň=ň nz
O=o=º=Ò=Ó=Ó=Ô=Õ=Ö=Ø=ò=ó=ó=ô=õ=ö=ø oe=Œ=œ oz P=p Q=q R=r=Ř=ř S=s=Ş=ş=Š=Š=š=š
sh ss=ß sz T=t=Ť=ť TM=tm=™ tz U=u=Ù=Ú=Ú=Û=Ü=ù=ú=ú=û=ü=Ū=ū=Ů=ů=Ų=ų ue uz V=v
W=w X=x Y=y=Ý=Ý=ý=ý=ÿ=Ÿ yz Z=z=Ž=Ž=ž=ž zh zz Þ=þ µ
如果您认为 ƒ
是重音字母,那么您可能也想处理它。
你的问题很有趣。
我有一个很大的 MySQL
、InnoDB
table,它在 utf8mb4_unicode_ci
中保存数据。我有几乎所有基于拉丁字母的语言的记录。我可以轻松地搜索带有重音字符的单词并找到具有不同变体的结果 (accented/not-accented),但土耳其语存在问题。当您指定包含大 I
字母的单词时,基本 LIKE
关键字在 SQL
行中不起作用。我希望看到所有包含该字母小写版本的单词(无点 i
)。
因此,I
在英语中是 i
,但在土耳其语中是 dotless i
。 (ı
)
SELECT * FROM words WHERE word LIKE 'SIR'
字不带sır
字。它只带来 sir
个词,但它们都存在于同一个 table.
你遇到过这样的问题吗? SQL
如何解决?
更新:
SELECT * FROM words WHERE word LIKE 'SIR'
COLLATE utf8mb4_turkish_ci
returns sır
但不是 sir
。尽管这可以解决一些问题,但不幸的是,从这个查询到 return 需要 23 秒而不是 0.00003 秒(没有 COLLATE
关键字)
这是一般 unicode 文本处理的已知棘手问题。您所能做的就是对具有不同形式 i 的单词使用 OR
或使用正则表达式模式。
索引还是扫描?
在您的示例中,我假设 word
已编入索引? table 相当大?在这种情况下,索引对于查找匹配 指定排序规则 的行非常有用。任何其他排序规则(您使用 COLLATE ...
的情况)需要忽略索引并扫描 整个 table(慢)。
使用 REGEXP
将 也 需要完整的 table 扫描。
即时执行 REPLACE(...)
需要完整的 table 扫描。
因此,假设有 "too many" 行可以进行完整的 table 扫描,没有简单的方法可以搜索 sır
或 sir
任意归类。让我们寻找另一种方式...
首先,让我们看一些整理案例。
在大多数 utf8 归类中,包括 utf8_unicode_ci,I=i=Ì=Í=Í=È=Ï=ì=í=í=î=ï=Ī=ī=Ç=į=İ
在 utf8_turkish_ci 中,I=ı,但它们出现在 i=Ì=Í=Í=È=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ 之前(因此,解释了你的部分问题)。
大多数其他 utf8 归类将 ı 视为介于 i 和 j 之间。
utf8_general_ci 略有不同:I=i=Ì=Í=Í=È=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ=ı
utf8_icelandic_ci 将一些带重音符号的 i 视为不同的字母:I=i=Ì=È=Ï=ì=î=ï=Ī=ī=Į=į=İ,但 Í=Í=í=í 介于两者之间I 和 J。那个人也在 Z 之后对这些进行排序: Ä=Æ=ä=æ Ö=Ø=ö=ø Å=å
见我的Reference
另一个问题:重音字母 可以 显示为两个 utf8 字符 - 字母,然后是 "non-spacing mark"
那么,怎么办??
计划 A:构建您自己的归类。这需要一些工作,但并非不可能。这将是最佳的,为您提供最佳性能。正如我们将在下面看到的,utf8_unicode_520_ci 非常接近,可以作为一个起点。
计划 B:在您的 table 中添加另一列;我们称它为 wordx
。它会有 word
,但会去除高重音。然后索引 wordx
而不是 word
。所以 word='sır' 的行会有 wordx='sir'.
计划 C:使用上面讨论的等效项,如果 "I" 从每个组中选择一种类型用于 table 中定义的排序规则,然后使用utf8_unicode_520_ci
与 UNION
:
( SELECT ... WHERE word = 'sir' )
UNION ALL
( SELECT ... WHERE word = 'sır' )
这应该包含 i
的所有风格。
哎呀,如果单词有多个不同的口音table字母怎么办?乍一看,这可能不是问题——所有 a
在 utf8_unicode_520_ci 中整理相等。浏览其余的字母,除了 ı
出现问题外,我没有看到任何其他内容。
下面是 utf8_unicode_520_ci
的有趣 等价物:
A=a=ª=À=Á=Á=Â=Ã=Ä=Å=à=á=á=â=ã=ä=å=Ā=ā=Ą=ą Aa ae=Æ=æ az B=b C=c=Ç=ç=Č=č ch cz
D=d=Ð=ð=Ď=ď dz E=e=È=É=É=Ê=Ë=è=é=é=ê=ë=Ē=ē=Ĕ=ĕ=Ė=ė=Ę=ę=Ě=ě F=f fz ƒ
G=g=Ğ=ğ=Ģ=ģ gz H=h hz I=i=Ì=Í=Í=Î=Ï=ì=í=í=î=ï=Ī=ī=Į=į=İ ij=ij iz ı J=j
K=k=Ķ=ķ L=l=Ĺ=ĺ=Ļ=ļ=Ł=ł lj=LJ=Lj=lj ll lz M=m N=n=Ñ=ñ=Ń=ń=Ņ=ņ=Ň=ň nz
O=o=º=Ò=Ó=Ó=Ô=Õ=Ö=Ø=ò=ó=ó=ô=õ=ö=ø oe=Œ=œ oz P=p Q=q R=r=Ř=ř S=s=Ş=ş=Š=Š=š=š
sh ss=ß sz T=t=Ť=ť TM=tm=™ tz U=u=Ù=Ú=Ú=Û=Ü=ù=ú=ú=û=ü=Ū=ū=Ů=ů=Ų=ų ue uz V=v
W=w X=x Y=y=Ý=Ý=ý=ý=ÿ=Ÿ yz Z=z=Ž=Ž=ž=ž zh zz Þ=þ µ
如果您认为 ƒ
是重音字母,那么您可能也想处理它。
你的问题很有趣。