【问题标题】:Is there a better way to build this MySQL query with extensive WHERE conditions?有没有更好的方法来构建这个具有广泛 WHERE 条件的 MySQL 查询?
【发布时间】:2013-03-08 18:51:02
【问题描述】:

要求是获取用户提供的关键字列表,并返回在 16 个字段中的任何一个字段中包含任何关键字的任何记录。

所以如果用户输入关键字    cup          面包
(关键字的顺序并不重要,它们之间没有任何隐含的关系。)

所以 WHERE 条件的数量是 78:

WHERE ObjObjectName LIKE '%cup%'
   OR ObjObjectName LIKE '%dog%'
   OR ObjObjectName LIKE '%bread%'
   OR ObjObjectOtherName LIKE '%cup%'
   OR ObjObjectOtherName LIKE '%dog%'
   OR ObjObjectOtherName LIKE '%bread%'
   OR ObjObjectID LIKE '%cup%'
   OR ObjObjectID LIKE '%dog%'
   OR ObjObjectID LIKE '%bread%'
   OR ObjOtherName LIKE '%cup%'
   OR ObjOtherName LIKE '%dog%'
   OR ObjOtherName LIKE '%bread%'
   OR ObjTitle LIKE '%cup%'
   OR ObjTitle LIKE '%dog%'
   OR ObjTitle LIKE '%bread%'
   OR ObjCategory LIKE '%cup%'
   OR ObjCategory LIKE '%dog%'
   OR ObjCategory LIKE '%bread%'
   OR AccCreditLineLocal LIKE '%cup%'
   OR AccCreditLineLocal LIKE '%dog%'
   OR AccCreditLineLocal LIKE '%bread%'
   OR PrimaryCreator LIKE '%cup%'
   OR PrimaryCreator LIKE '%dog%'
   OR PrimaryCreator LIKE '%bread%'
   OR EdiPublisherLocalSummary LIKE '%cup%'
   OR EdiPublisherLocalSummary LIKE '%dog%'
   OR EdiPublisherLocalSummary LIKE '%bread%'
   OR EdiPlaceOfPublication LIKE '%cup%'
   OR EdiPlaceOfPublication LIKE '%dog%'
   OR EdiPlaceOfPublication LIKE '%bread%'
   OR CreContinent LIKE '%cup%'
   OR CreContinent LIKE '%dog%'
   OR CreContinent LIKE '%bread%'
   OR CreSubContinent LIKE '%cup%'
   OR CreSubContinent LIKE '%dog%'
   OR CreSubContinent LIKE '%bread%'
   OR CreCountry LIKE '%cup%'
   OR CreCountry LIKE '%dog%'
   OR CreCountry LIKE '%bread%'
   OR CreRegion LIKE '%cup%'
   OR CreRegion LIKE '%dog%'
   OR CreRegion LIKE '%bread%'
   OR CreCounty LIKE '%cup%'
   OR CreCounty LIKE '%dog%'
   OR CreCounty LIKE '%bread%'
   OR CreStateProvince LIKE '%cup%'
   OR CreStateProvince LIKE '%dog%'
   OR CreStateProvince LIKE '%bread%'
   OR CreCity LIKE '%cup%'
   OR CreCity LIKE '%dog%'
   OR CreCity LIKE '%bread%'
   OR CreContinent1 LIKE '%cup%'
   OR CreContinent1 LIKE '%dog%'
   OR CreContinent1 LIKE '%bread%'
   OR CreSubContinent1 LIKE '%cup%'
   OR CreSubContinent1 LIKE '%dog%'
   OR CreSubContinent1 LIKE '%bread%'
   OR CreCountry1 LIKE '%cup%'
   OR CreCountry1 LIKE '%dog%'
   OR CreCountry1 LIKE '%bread%'
   OR CreRegion1 LIKE '%cup%'
   OR CreRegion1 LIKE '%dog%'
   OR CreRegion1 LIKE '%bread%'
   OR CreCounty1 LIKE '%cup%'
   OR CreCounty1 LIKE '%dog%'
   OR CreCounty1 LIKE '%bread%'
   OR CreStateProvince1 LIKE '%cup%'
   OR CreStateProvince1 LIKE '%dog%'
   OR CreStateProvince1 LIKE '%bread%'
   OR CreCity1 LIKE '%cup%'
   OR CreCity1 LIKE '%dog%'
   OR CreCity1 LIKE '%bread%'
   OR CreDateCreated LIKE '%cup%'
   OR CreDateCreated LIKE '%dog%'
   OR CreDateCreated LIKE '%bread%'
   OR CreMarkSignature LIKE '%cup%'
   OR CreMarkSignature LIKE '%dog%'
   OR CreMarkSignature LIKE '%bread%'

这真的是最好的方法吗?我的意思是,我打算使用 PDO 准备好的语句,我发现这个 Q&A (LIKE query using multiple keywords from search field using PDO prepared statement) 非常有帮助,但是我对 MySQL 相对缺乏经验,所以我不确定是否有更好的方法来处理所有那些条件.谢谢!

【问题讨论】:

  • 如果你更好地格式化这个,我们可以看到 78 WHERE ...
  • 您可以使用REGEXP 去掉每个字段的三个LIKEs:WHERE SomeObject REGEXP 'cup|dog|bread'
  • NominSim - 谢谢,我会试试下面列出的 Mikhal 的额外 Concat 想法。 @biziclop-感谢重新格式化!
  • 问题:关键字“cup”是否也应该匹配“hiccup”?
  • @ChrisTravers - 好问题。不,最好它不会返回“打嗝”。但是,这是一个博物馆对象数据库,通常不会有那么多重叠。 “蓝瓷瓷器”不会返回很多误报。但是我明白了我需要仔细考虑我对 % 的使用的要点。谢谢!

标签: mysql where


【解决方案1】:

您可以使用正则表达式和连接:

WHERE CONCAT(
  ObjObjectName, 
  ObjObjectOtherName, 
  ObjObjectID, 
  ObjOtherName,
  ObjTitle,
  ObjCategory,
  AccCreditLineLocal,
  PrimaryCreator,
  EdiPublisherLocalSummary,
  EdiPlaceOfPublication,
  CreContinent,
  CreSubContinent)
  REGEXP 'cup|dog|bread'

【讨论】:

  • 谢谢米哈伊尔!我会试试的。我想知道这是否仍然适用于准备好的语句......其中我可以使用 REGEXP :keywords 和 $s->bindValue(':keywords', 'cup|dog|bread']);我要去上班了。谢谢!
  • 想指出,除非每列只有一个单词,否则您不会从任何索引中受益。对于原始的LIKE,似乎一列中有多个单词。如果REGEXP 比没有索引的LIKE 链更有效,那么使用索引会带来更多好处。但这一切都取决于您要搜索的记录数。您现在可能会发现它可以工作,但以后可能会遇到问题。
  • @Luke - 我们有 85000 条记录,可能会达到 200,000 条左右...感谢您提醒我要向前看。绝对不想在 5 年后重温这一切。
【解决方案2】:

您需要使用Full-Text search。请记住,MySql 的全文索引仅限于 4 个以上的字母单词。所以“狗”是行不通的。你可以编译 MySQL 并改变它。 Sphinx 通常更适合较小的单词和更快的查找。

我还建议查看MariaDB,它是 MySQL 的直接替代品,由原始 MySQL 开发人员创建。 MariaDB 有一个Sphinx storage engine,它使集成更容易。

【讨论】:

  • 谢谢卢克。由于我对全文搜索的了解有限,这似乎不是正确的解决方案。两个和三个字母的单词将是有效的关键字。
  • 好吧,当你开始遇到性能问题时,再看看全文。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 2012-01-17
相关资源
最近更新 更多