MySQL - 如何执行此字符串搜索?

时间:2015-01-14 11:16:01

标签: mysql string search

我有一个包含37列,各种类型,INT和VARCHARS以及2个LONGTEXT列的表。客户端希望搜索以搜索表并找到匹配的行。

但是,我遇到了麻烦。这是我到目前为止所做的:

1)我最初的看法是做一大堆OR查询 - 但是我被推迟了这个事实我需要提供30次搜索数据,这是大量的重复,我确定那里;比这更好的方式。

代码:

SELECT
  MemberId,
  MemNameTitle,
  MemSName,
  MemFName,
  MemPostcode,
  MemEmail
FROM
  MemberData
WHERE
  MemFName LIKE CONCAT('%',?,'%') OR
  MemSName LIKE CONCAT('%',?,'%') OR
  MemAddr LIKE CONCAT('%',?,'%') OR
  MemPostcode LIKE CONCAT('%',?,'%') OR
  MemEmail LIKE CONCAT('%',?,'%') 
 ...etc...

等。等等。这是一大堆OR并且非常笨拙。

2)我以为我会尝试重做它以将所有列放在括号中然后只询问一次查询,我在SO上看到了类似的代码,但不确定它是否正常工作,但它至少是一个侮辱:

    SELECT
      MemberId,
      MemNameTitle,
      MemSName,
      MemFName,
      MemPostcode,
      MemEmail
    FROM
      MemberData 
    WHERE
      (MemNameTitle OR
       MemFName OR
       MemSName OR
       MemAddr OR
       MemPostcode OR
       MemEmail OR
       MemSkype OR
       MemLinkedIn OR
       MemFacebook OR
       MemEmailTwo ...etc...) LIKE CONCAT('%',?,'%')
     GROUP BY
       MemberId 

此代码在没有明显错误的情况下执行但失败,因为它始终不返回任何结果,如在返回的0字段中。从最初的角度来看,我无法理解为什么

3)所以,通过对操作系统的一些研究,我发现了使用IN关键字的重新排列,但是根据此处Is it possible to use LIKE and IN for a WHERE statment?的先前问题,它似乎无效。

我想得到的是:

SELECT
  MemberId,
  MemNameTitle,
  MemSName,
  MemFName,
  MemPostcode,
  MemEmail
FROM
  MemberData
WHERE
  MemNameTitle,
  MemFName,
  MemSName,
  MemAddr,
  MemPostcode,
  MemEmail,
  MemSkype,
  MemLinkedIn,
  ...etc ...
  MemFax,
  MemberStatus,
  CommitteeNotes,
  SecondAddr,
  SecondAddrPostcode IN (LIKE CONCAT('%',?,'%')  )

这是crudy语法但我希望你能得到我想要的想法,我想使用LIKE %%子句搜索许多字段以获得相同的值。字段是各种TEXT / VARCHAR类型。

4)然后我研究了MySQL全文搜索,但这很快变得无用,因为这只适用于TEXT类型而不是VARCHAR类型搜索。我在每次搜索之前都考虑过将每个VARCHAR列更改为TEXT列,但认为这也是相对处理器密集型的,并且对于许多人必须要执行的搜索而言似乎不合逻辑?

所以,我没有想法.....你能帮助我这样搜索吗?或者为什么我的代码在尝试2中总是返回Zero行?

干杯

额外工作:

5)我一直在考虑重新安排IN子句声明并提出这个:

    SELECT *(lazy typing!) WHERE
     CONCAT('%',?,'%') IN
 (MemNameTitle, 
MemFName, 
MemSName, 
MemAddr, 
MemPostcode, 
MemEmail, 
MemSkype, 
...etc...
    CommitteeNotes,
 SecondAddr,
 SecondAddrPostcode) 
GROUP BY MemberId 

但是这会返回一个结果,但结果始终是表的最后一行。这不起作用。

解决方案1:

从Ravinder,对所有领域使用CONCAT_WS - 这在我的情况下有用,虽然我脑子里的东西确实发现CONCAT有些难看,但是很好。

SELECT * FROM MemberData WHERE
 CONCAT_WS('<*!*>', 
MemNameTitle, MemFName, MemSName, 
MemAddr, MemPostcode, MemEmail, 
MemSkype, MemLinkedIn,
...etc...
MemberStatus, CommitteeNotes, SecondAddr,
 SecondAddrPostcode)
 LIKE CONCAT('%',?,'%') 
GROUP BY MemberId ";

该表最终将有几千行,我有点担心,因为这个查询将为每次搜索在表格上的每一行连续24列,这可能很容易变得非常昂贵和低效(即慢) ,所以如果有人有任何方式

i)在没有CONCAT列或

的情况下进行搜索

ii)使此解决方案更快/更有效

请分享!!

2 个答案:

答案 0 :(得分:2)

有一种解决方法。但我觉得这太粗糙了,表现可能不那么好。

where
 concat_ws( "<*!*>", col1, col2, col3, ... ) like concat( '%', ?, '%' )

在这里,我使用'<*!*>'作为示例分隔符 您必须使用模式字符串作为分隔符,您确定,

  1. 不是占位符值或
  2. 的一部分 当2个或更多列时,
  3. 不是生成的字符串的一部分 级联
  4. 请参阅文档

    MySQL: CONCAT_WS(separator,str1,str2,...)
    它不会跳过空列值,但会跳过NULL。

答案 1 :(得分:0)

一种相当丑陋的方法是

SELECT
  MemberId,
  MemNameTitle,
  MemSName,
  MemFName,
  MemPostcode,
  MemEmail
FROM
  MemberData
WHERE
CONCAT(
  MemNameTitle,
  MemFName,
  MemSName,
  MemAddr,
  MemPostcode,
  MemEmail,
  MemSkype,
  MemLinkedIn,
  ...etc ...
  MemFax,
  MemberStatus,
  CommitteeNotes,
  SecondAddr,
  SecondAddrPostcode) LIKE CONCAT('%',?,'%')

因此,您首先连接要搜索的所有列,然后查看生成的大字符串以查找文本。

但我想你可以看到这远远不是高效和最佳的。但是,由于您在搜索的开头和结尾使用了%符号,因此无论如何都无法使用任何索引。

警告: 请注意,如果您的某列包含空值,则此CONCAT可能会失败,因为整个CONCAT将返回null!