在将问题标记为重复之前,请仔细阅读该问题。事实并非如此。
我有一个名为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。