【问题标题】:How to determinate if the element 'word4' of the string 'word1;word2;word3;word4' is in the string 'word4','word5','word6','word7'?如何确定字符串'word1;word2;word3;word4'的元素'word4'是否在字符串'word4','word5','word6','word7'中?
【发布时间】:2013-10-28 10:32:43
【问题描述】:

在我的网站上,我有一个系统可以对表 T.Categories 上的内容进行分类,该字符串看起来像

category1;category2;category3;category4

(可能或多或少)。

另一方面,我让我的用户选择他们感兴趣的类别。基本上,他们在表单上做出选择,结果列在 PHP 变量 $var 中,看起来像

category2','category4','category5

(等等)

通过请求

T.Categories IN ('".$var."'))";

我能够确定内容是否符合他们的兴趣,只有当内容归入一个单一类别时。

举例:

  • 我有一张名为“猫”类别的照片
  • 我的用户想要查看属于“猫”和“狗”类别的照片
  • 我的 SQL 请求看起来像 SELECT * FROM T Where T.Categories IN ('".$var."'))";

实际上,我告诉 SGBD 观察 T.Categories 的内容是否在列表 $var 中

当 T.Categories 中只有一个类别时,它可以工作。 “Cat 在 $var 中吗?是的,Cat 在 'Cat','Dog' 中。然后我将内容提供给用户(因为 Cat 在 $var 中)”

但是如果 T.Categories 中有多个类别,它就不再起作用了。因为整个类别都存储在 category1;category2;category3;category4 的形式下。不高兴: 字符串 'Cat;Horse;Duck' 不在 'Cat','Dog' 中(MySQL 正在寻找整个字符串)

我需要将 Cat;Horse;Duck 分成三个部分进行解析,以使 SGBD 在 $var 列表中查找每个部分。 Cat IN $var 吗?是的,猫喜欢“猫”、“狗”。 马在 $var 中吗?不,马不喜欢“猫”、“狗”。 Duck 在 $var 中吗?不,鸭子不喜欢“猫”、“狗”。 然后我将内容提供给用户(因为 Cat 在 $var 中)。

我怎样才能使用一个请求来达到我的目标?

【问题讨论】:

  • 你需要实现一个合适的搜索引擎;比如solr。开始here,然后here
  • 在我学习的这一点上对我来说可能有点难,但绝对很有趣!谢谢

标签: mysql string parsing in-clause


【解决方案1】:

您的设计有问题。您不应该将类别存储在 MySQL 中的字符串中。

您应该将类​​别存储在一个新表中,并使用many-to-many 表将两者链接起来:

一旦您有一个多对多表将您的文章链接到您的类别,您就可以根据类别检索文章,并评估与所需关键字的匹配程度。

SELECT A.*, L.Relevance
FROM Article AS A
INNER JOIN
(
    SELECT AC.ArticleID, COUNT(AC.CategoryID) AS Relevance
    FROM ArticleCategory AS AC
    INNER JOIN Category AS C
    ON AC.CategoryID = C.CategoryID   
    WHERE C.Name IN ('Cat','Dog','Donkey','Chicken')
    GROUP BY AC.ArticleID
) AS L
ON A.ArticleID = L.ArticleID
ORDER BY L.Relevance DESC, Name

您可以看到example in SQLFiddle

您还可以在此处获取更多信息:

另一种方法是使用 MySQL 中的全文搜索功能。更多信息在这里:

【讨论】:

    【解决方案2】:

    确实,您应该为每个用户将类别存储在行中,而不是这样做,这将使您的查询变得简单并且更加规范化。但是,这意味着您的表结构会发生变化。

    如果你不能这样做,你可以像这样生成你的选择请求:

    SELECT * FROM T Where concat(';', T.Categories, ';') like '%;cat;%' or
                          concat(';', T.Categories, ';') like '%;dog;%'
    

    如果您使用前导和尾随分号存储T.Categories,则不需要使用concat。这意味着对表 T 进行扫描,即无法使用索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 2019-06-11
      • 2011-11-13
      相关资源
      最近更新 更多