0

我正在用 PHP 创建一个程序,用户在其中提交文件,然后可以根据他们最初创建文件时输入的 6 个类别来搜索文件。类别存储在一个单元格中的表格中,如下所示: category_1 category_2 category_3 etc - 它们不在单独的列中

我需要创建一个页面,用户可以在其中填写他们想要搜索的类别,然后将查询提交到 MYSQL 数据库。我希望页面首先对文件匹配最多类别的行进行排序。

我的问题是如何设置 MYSQL 查询以搜索 6 个类别,然后按类别匹配最多的行对结果进行排序(在匹配 2 个类别的前面显示具有 3 个匹配类别的那个?

我会提出我尝试过的代码,但我什至不知道从哪里开始(我使用正则表达式吗?)。任何帮助都会很棒。我熟悉 PHP 和 HTML,但 MYSQL 对我来说是新的。

4

3 回答 3

0

假设类别位于名为@Categories 的列中。为方便起见,我将假设它们是逗号分隔的,而不是空格分隔的(您可以在下面的代码中使用替换)。这简化了解释。

select
from files f
order by (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 1))), ',' 1), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 2)), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 3)), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ', ', 4), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 5)), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 6)), ',' 1)), f.categories) > 0) desc

(注意:这是未经测试的。)

关键是表达式:

      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', <n>)), ',' 1)), f.categories) > 0) +

让我们从里到外解释一下:

该表达式substring_index(@Categories, ',', <n>)返回类别字符串,直到第 n 个类别。

然后reverse反转这个字符串,所以现在第 n 个是第一个。

nextsubstring_index返回此字符串的第一个元素,即原始字符串的第 n 个元素。但是,它被颠倒了,所以下一个reverse。最后,find_in_set()在文件的类别中查找此内容。

整个order by子句将这些值加在一起(布尔加起来就像 MySQL 中的整数一样)。所以,你得到了匹配的数量——这就是你想要对原始数据进行排序的方式。

综上所述,这是一个糟糕的数据结构。如果您以更规范的形式存储它,则解决方案会容易得多。

于 2013-06-10T02:16:14.793 回答
0

您应该调查在布尔模式下使用 MySQL 的 FULLTEXT 搜索。

http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html

尤其是当您将类别串联在一个列中时,这很可能是解决问题的好方法。

您需要使用 MyISAM 作为您以这种方式搜索的一个或多个表的访问方法。

(注意:如果您不使用布尔模式全文搜索很难在小表上进行测试;它对小型文本语料库的词频感知会产生不可预测的结果。但使用布尔模式就可以了。)

于 2013-06-10T01:55:37.450 回答
0

这应该适合你:

 select 
    id, 
    name, sum(
       IF(find_in_set('$cat1', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat2', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat3', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat4', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat5', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat6', replace(' ',',','categories'), 1, 0)) as match_score
 from products
    where match_score > 0 
 order by match_score desc;
于 2013-06-10T02:19:54.140 回答