MySQL 复杂字符串匹配
Posted
技术标签:
【中文标题】MySQL 复杂字符串匹配【英文标题】:MySQL complex string matching 【发布时间】:2017-12-25 07:53:47 【问题描述】:我有一个 mysql 表,我在其中存储带有 PartNumber 字段的行,用于存储来自不同公司的库存数据。公司有不同的方式来传达相同的 PartNumber。
例如,假设我们有 PartNumber ROF-137-7516。同一部分可能具有该 PartNumber 的以下迭代:
ROF1377516
ROF1377516/R2
ROF 137 7516-2
ROF 137 7516/1
ROF 137 7516/1 R3D
ROF137 7516/2
ROF1377516/1
ROF-137-7516/2
我想要一个在用户输入“ROF-137-7516”搜索词时获取所有这些部分的查询。这是目前我的查询...
select * from parts where PartNumber like 'ROF-137-7516%';
但这只会返回最后一行。是否可以编写一个返回所有部分的查询?
【问题讨论】:
【参考方案1】:如果你想在 SQL 中处理这个问题,这是REPLACE()
的一种方法:
SELECT *
FROM Parts
WHERE REPLACE(REPLACE(PartNumber,'-',''),' ','') LIKE REPLACE('ROF-137-7516%','-','')
这假设他们将始终输入带有-
或不带空格的PartNumber
。
【讨论】:
请记住,直接查询 PartNumber 将使用索引(如果存在),但查询REPLACE(PartNumber, [...])
将意味着优化器将不再能够使用索引(因为您不是实际比较索引中的 PartNumber 值,而是一些动态生成的数据)。
谢谢。不完美,但绝对比我迄今为止想出的任何东西都要好。
我稍微调整了你的 where 子句,这样即使他们输入带有空格的 PartNumber,我仍然会得到正确的匹配。 REPLACE(REPLACE(partNumber,'-',''),' ','') LIKE REPLACE(REPLACE('$partNumber%','-',''),' ','') 肯定慢一点,但它仍然足够快,可以作为一个可接受的解决方案。【参考方案2】:
您可能希望通过几种方法来执行此操作,具体取决于列中的数据,以及您需要什么样的性能才能摆脱表格。有关详细信息,请参阅 MySQL pattern matching 页面。
1)
根据您在 PartNumber 中可以预期的值,您可以将破折号替换为 %
通配符,以匹配 0 个或多个任意字符:
select * from parts where PartNumber like 'ROF%137%7516%'
但这对您来说可能还不够。例如,它会错误地返回具有以下值的行:ROF 123 137XX/7516
2)
如果您在 ROF 和其他数字之间总是有一些字符,那么您可以在搜索模式中使用 _
。
select * from parts where PartNumber like 'ROF_137_7516%'
但是,该匹配要求值之间恰好有一个字符,因此它不会匹配ROF1377516
,也不会匹配ROF - 137 7516
。
3.1)
运行查询的最准确方法是使用正则表达式。但是,正则表达式会极大地影响您的性能;所以要谨慎使用它。在您的情况下,您使用.*
匹配任何字符(.
)零 次或多次(*
):
select * from parts where PartNumber regexp 'ROF.*137.*7516.*'
您可能会发现在 7516 中的 137 之前匹配“无限”个字符太多了。例如,它会错误地匹配:ROF 123 137XX/7516
。您可能已经注意到,这与上面的 #1 完全相同。
3.2)
如果.*
/ %
太宽泛,那么您可以限制.
匹配的字符数。假设数字之间有一个字符(空格、破折号等)是标准的,但您希望考虑到用户错误(例如没有分隔字符,或键入两个分隔字符而不是一个)。您可以使用0,#
来限制要匹配的字符数。假设 0 到 2 个字符:
select * from parts where PartNumber regexp 'ROF.0,2137.0,27516.*'
这样,它将匹配您问题中的所有示例模式,但不会匹配 ROF 123 137XX/7516
(因为“123”和“xx/”超过 2 个字符)
4) Aaron Dietz 回答了另一种技术,即使用 replace() 函数。根据您的表,这可能对您有用,但请记住,它将不再使用索引。表上的索引是针对列的原始值和数据类型的,但是通过 replace() 运行值将意味着索引值不能用于比较。
【讨论】:
以上是关于MySQL 复杂字符串匹配的主要内容,如果未能解决你的问题,请参考以下文章