所以,我有一个名为artcles的数据库,还有一个名为article标签的表。当用户查看文章时,我想查询最多五篇文章,这些文章的标签与正在查看的标签类似。这是我的两张桌子:
CREATE TABLE `articles` (
`article_id` int(15) NOT NULL AUTO_INCREMENT,
`parent_id` int(15) NOT NULL,
`author_id` int(15) NOT NULL,
`title` text NOT NULL,
`content` text NOT NULL,
`date_posted` text NOT NULL,
`views` int(15) NOT NULL,
`preview` text NOT NULL,
`status` tinyint(1) NOT NULL,
`modified_date` text NOT NULL,
PRIMARY KEY (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `article_tags` (
`tag_id` int(15) NOT NULL AUTO_INCREMENT,
`article_id` int(15) NOT NULL,
`keyword` varchar(250) NOT NULL,
PRIMARY KEY (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `articles` (
`article_id` int(15) NOT NULL AUTO_INCREMENT,
`parent_id` int(15) NOT NULL,
`author_id` int(15) NOT NULL,
`title` text NOT NULL,
`content` text NOT NULL,
`date_posted` text NOT NULL,
`views` int(15) NOT NULL,
`preview` text NOT NULL,
`status` tinyint(1) NOT NULL,
`modified_date` text NOT NULL,
PRIMARY KEY (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `article_tags` (
`tag_id` int(15) NOT NULL AUTO_INCREMENT,
`article_id` int(15) NOT NULL,
`keyword` varchar(250) NOT NULL,
PRIMARY KEY (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我已经尝试过编写自己的查询,但它们似乎从不起作用。我想在查询中使用连接,而不是使用CSV和LIKE。这是我到目前为止的查询:
这是我更新的查询:
SELECT A2.article_id, count(A2.article_id) AS matches
FROM article_tags AS A1 JOIN article_tags ON (A1.keyword = A2.keyword AND 1.article_id != A2.article_id)
JOIN articles ON (A2.article_id = A.article_id) AS A
WHERE A1.article_id = 1
GROUP BY A2.article_id
ORDER BY matches DESC
LIMIT 5"
$query = "
SELECT t2.article_id, count(t2.keyword) AS matches
FROM article_tags t1
JOIN article_tags t2 ON (t1.keyword = t2.keyword AND t1.article_id != t2.article_id)
WHERE t1.article_id = ".$article_id."
GROUP BY t2.article_id
ORDER BY matches DESC
LIMIT 5";
这是使用var_dump转储数组的结果
$query = "
SELECT t2.article_id, count(t2.keyword) AS matches
FROM article_tags t1
JOIN article_tags t2 ON (t1.keyword = t2.keyword AND t1.article_id != t2.article_id)
WHERE t1.article_id = ".$article_id."
GROUP BY t2.article_id
ORDER BY matches DESC
LIMIT 5";
array
0 =>
array
'article_id' => string '2' (length=1)
'matches' => string '1' (length=1)
array
0 =>
array
'article_id' => string '2' (length=1)
'matches' => string '1' (length=1)
答案 0 :(得分:0)
基本上你的想法是正确的 - 在article_tags
表上自我加入。有些事情你应该改进:
tag_id
而不是article_id
,因为您希望按相关性对文章进行排序,匹配标记的数量表示相关性。tag_id
而不是keyword
。加入非索引列将是性能问题。!=
。只需获取所有相关文章,然后删除最相关的文章,这应该是当前文章本身articles
。你自己不需要文章;在获得5篇相关文章后,只需在articles
上做一个简单的选择。所以答案可能是这样的:
SELECT
A2.article_id, count(A2.tag_id) AS matches
FROM
article_tags A1
JOIN
article_tags ON A1.tag_id=A2.tag_id
WHERE
A1.article_id = 1
GROUP BY
A2.article_id
ORDER BY
matches DESC
LIMIT 6 -- instead of 5, because the first result would be the current article
你应该得到一个包含6个ID的数组,然后删除第一个数组,然后执行SELECT(例如在python中):
article_ids = article_ids[1:]
articles = cursor.execute(
"SELECT * FROM articles WHERE article_id IN (%s)" % ",".join(article_ids)
)