MySQL复杂的字符串匹配

时间:2017-07-19 20:52:27

标签: mysql sql string where-clause string-matching

我有一个MySQL表,我在其中存储带有PartNumber字段的行,用于来自不同公司的库存数据。公司有不同的方式传达相同的PartNumber。

例如,假设我们有PartNumber ROF-137-7516 。同一部分可能具有该PartNumber的以下迭代:

select * from parts where PartNumber like 'ROF-137-7516%';

当用户输入" ROF-137-7516"的搜索字词时,我想要一个获取所有这些部分的查询。这是我目前的查询...

Models:
public function cover()
      {
         if(file_exists('/upload/cover/'.$this->immagine)) {
             return url('/upload/cover/'.$this->immagine);
         } else {
             return url('/upload/cover/no-cover.png');
         }
      }

Blade:
            <img src="{!! $info_giochi->cover() !!}"
            <img src="{{ url('upload/cover/'.$info_giochi->immagine) }}">

但这只会返回最后一行。是否可以编写一个返回所有部分的查询?

2 个答案:

答案 0 :(得分:2)

如果你想在SQL中处理这个问题,这里有REPLACE()的一种方式:

SELECT *
FROM Parts
WHERE REPLACE(REPLACE(PartNumber,'-',''),' ','') LIKE REPLACE('ROF-137-7516%','-','')

这假设他们将始终输入PartNumber -或没有空格。

答案 1 :(得分:0)

您可能希望通过以下几种方式执行此操作,具体取决于列中的数据以及退出表格所需的性能。有关详细信息,请参阅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,2}137.{0,2}7516.*'

这样,它会匹配您问题中的所有示例模式,但不匹配ROF 123 137XX/7516(因为“123”和“xx /”超过2个字符)

4) Aaron Dietz 回答了另一种技术,即使用replace()函数。根据您的表格,这可能对您有用,但请记住,它将不再使用索引。表上的索引是针对列的原始值和数据类型,但是通过replace()运行该值意味着索引值不能用于比较。