在where子句中使用数组,其中选中的字段包含昏迷分隔的单词


Using array in where clause, where the checked field contains coma separated words

在将问题标记为重复之前,请仔细阅读该问题。事实并非如此。

我有一个名为questions的表,该表中有字段questionMetaTags,它接受昏迷分隔值(关键字)

这是我的桌子:

`questionID` int(11) NOT NULL AUTO_INCREMENT,
`questioncategoryID` int(11) NOT NULL,
`questionstatusID` int(11) NOT NULL,
`organizationID` int(11) NOT NULL,
`legalformID` int(11) DEFAULT NULL,
`questionProtocolID` varchar(45) DEFAULT NULL,
`questionDisplayedRecordID` int(11) NOT NULL,
`questionTitle` text NOT NULL,
`questionSummary` text,
`questionText` longtext NOT NULL,
`questionAnswerSummary` text,
`questionAnswerText` longtext,
`questionMetaTags` text,
`questionAskedBy` int(11) NOT NULL,
`questionAnsweredBy` int(11) DEFAULT NULL,
`questionAskedOnDate` datetime NOT NULL,
`questionAnsweredOnDate` datetime DEFAULT NULL,
`questionAskedFromIp` varchar(255) NOT NULL

我正在尝试创建一个将"生成"相关问题的查询。我在我的页面上显示一个特定的问题,我希望下面只显示以下问题:1.属于同一类别2.至少有两个或两个以上相同的关键词

在这两个变量中,我持有所显示问题的类别和关键字,现在我想构建一个显示"相关"问题的查询。

$keywordsInQurrentQuestion (array that holds the keywords)
$questioncategoryID (category of the question)

我正在尝试类似的东西:

SELECT *
   FROM question WHERE `questionstatusID` = 5
   AND questioncategoryID = $questioncategoryID
   // I have no idea how to check if the question have at least 2 keywords that exists in the $keywordsInQurrentQuestion array
   ");

我已经找到了如何在where子句中使用数组的答案,因为我想检查至少两个相同的关键字,这些答案对我没有帮助。

您的数据库模式并不是为这种查询而设计的。MySQL毕竟是一个关系型数据库。

MySQL中的解决方案(需要更改数据库模式)

最好只为关键字(或元标签)提供一个额外的表:

ID      tag
  1     oranges
  2     apples
...     ...
154     motor oil

第二个表将保存问题和标签之间的关系:

questionID tagID
  1          1
  1          2
  1         37
  2          3
...        ...
 18        102
 19        154

现在,当查询类似/相关的问题时,可以通过检查最少的相同标签来完成。首先,使用子查询从显示的问题中获取所有标签:

SELECT tagID FROM relations WHERE questionID = 123;

然后,这将用于检索类似问题的实际查询:

SELECT DISTINCT(r1.questionID)
FROM relation r1
INNER JOIN relation r2
  ON r1.questionID = r2.questionID AND NOT r1.tagID = r2.tagID
WHERE r1.tagID IN (SELECT tagID FROM relations WHERE questionID = 123)
  AND r2.tagID IN (SELECT tagID FROM relations WHERE questionID = 123)

此查询将关系表与自身连接(selfjoin),查找具有相同问题ID但不同标记ID的行。在WHERE子句中,它检查两个连接的标记是否都在原始问题的集合中。最后,它将删除所有重复项(DISTINCT),并为您提供相关问题ID的列表。

这个查询仍然需要扩展以检查类别,为了使语句清晰,这一点被省略了。

PHP中的解决方案

根据您的评论,您不想更改DB模式。尽管从执行时间和性能来看,先从数据库中检索所有问题,然后用PHP获取相关问题可能不是最佳选择,但这仍然是可能的。

假设你在某个价值中拥有原始问题的所有条款

$meta_tags = "oranges,apples,avocados,olive oil";

以及在一个数组中来自同一类别的所有问题,该数组至少包含问题ID和相应的关键字

$questions = array(
  0 => array(
    "questionID" => 1,
    "metaTags" => "apples,olive oil",
  ),
  1 => array(
    "questionID" => 2,
    "metaTags" => "oranges,motor oil",
  ),
  2 => array(
    "questionID" => 3,
    "metaTags" => "oranges,avocados",
  ),
  ...
);

您可以循环浏览您的问题,检查是否至少有两个关键字相同,然后将问题ID存储在某个数组中:

function check_tags($needles, $haystack) {
  $original_tags = explode(',', $haystack);
  $original_tags = array_map('trim', $original_tags);
  $tags_to_check = explode(',', $needles);
  $tags_to_check = array_map('trim', $tags_to_check);
  $count = 0;
  foreach ($tags_to_check as $t) {
    if (in_array($t, $original_tags)) {
      count++;
    }
  }
  return $count;
}
$related = array();
foreach ($questions as $q) {
  if (check_tags($q['metaTags'], $meta_tags) >= 2) {
    $related[] = $q['questionID'];
  }
}

数组$related现在包含与原始问题相似的所有问题ID。