我有三张桌子:文章,标签和articles_tags。可以想象,每篇文章都可以有多个标签,每个标签都可以分配给多篇文章。我有所谓的主要文章(由唯一的URL表示),并希望得到它的相关文章,基于它们之间的共享标签,如:如果主要文章和第2条有一个共同的标签,显示两篇文章(理想情况下,它不会在结果中显示/包含主要文章)。主要文章的唯一URL在SQL查询中传递。
预期的结果超出了我的意愿,所以任何帮助都会受到赞赏。
如果以上网站脱机,则复制代码:
数据库和内容:
CREATE TABLE `articles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`status` tinyint(4) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tag` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `articles_tags` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`article_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `articles` (`url`, `title`, `status`) VALUES
('test-article-1', 'Test Article #1', 1),
('test-article-2', 'Test Article #2', 1),
('test-article-3', 'Test Article #3', 0),
('test-article-4', 'Test Article #4', 0),
('test-article-5', 'Test Article #5', 1);
INSERT INTO `tags` (`tag`, `url`) VALUES
('Test', 'test'),
('City', 'city'),
('Nature', 'nature');
INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 2),
(3, 1),
(3, 2),
(4, 2),
(5, 1);
最新(不正常)SQL查询:
SELECT
tags.tag,
articles.url,
articles.title
FROM articles
LEFT JOIN articles_tags ON articles_tags.article_id=articles.id
LEFT JOIN tags ON articles_tags.tag_id=tags.id
WHERE (articles.url='test-article-1'
OR tags.id IN (articles_tags.tag_id))
AND articles.status=1
GROUP BY articles.id
结果: 正如你在SQLFiddle上看到的,它显示了第1,2和5条,但在我看来它应该只显示1和5
预期成果:第1条和第5条,理想情况下只有5条(不包括第1条,因为它是主要条款)。
答案 0 :(得分:0)
我不太清楚我理解你为什么不期望你的结果中的第2条,因为它和第1条都有标记2.这下面仍然应该返回第2条,所以它可能不是你想要的,但这是最直接的#34;同样标记的排名"查询我能想到:
SELECT b.*, COUNT(1) AS tagMatches
FROM articles AS a
INNER JOIN articles_tags AS aTags ON a.id=aTags.article_id
INNER JOIN articles_tags AS bTags
ON aTags.article_id<>bTags.article_id
AND aTags.tag_id = bTags.tag_id
INNER JOIN articles AS b ON bTags.article_id
WHERE a.url = ?
GROUP BY b.url
ORDER BY tagMatches DESC, b.title
;
编辑:这假设文章不能多次使用相同的标签。如果不是这种情况,它会使排名偏差(但如果重复的标签应该有更多的权重,这可能是有利的。)
Edit2:值得注意的是,*
可能不应该用于最终结果;为了简单起见,我在这里使用它。
答案 1 :(得分:0)
OR
条件OR tags.id IN (articles_tags.tag_id))
会触发这些行:
INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES
(1, 1),
...
(3, 1),
...,
(5, 1);
所以,对我来说结果看起来很好