我有两个MySQL表:Articles
和SimilarArticles
。
CREATE TABLE `Articles` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`text` text,
`priority` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `SimilarArticles` (
`article_id` int(11) unsigned NOT NULL,
`similar_article_id` unsigned NOT NULL,
PRIMARY KEY (`article_id`,`similar_article_id`)
)
SimilarArticles
是一个简单的关系表,用于跟踪类似的文章记录。
this post中的用户totymedli有一个很好的解释如何在这种情况下选择类似的记录,这很好。
但是现在我必须创建一个SELECT语句,以确保结果中有没有类似的文章。因此,对于表中所有类似文章组,只有字段priority
中具有最高值的记录才会进入结果集。
到目前为止,我还没有想出办法。有谁知道如何在MySQL中有效地做到这一点?
表格文章
id text priority
1 FooA 1
2 Bar 1
3 FooB 3
4 FooC 2
5 Baz 9
表格类似文章
article_id similar_article_id
1 3
4 1
3 4
我正在尝试创建的SELECT语句应返回:
id text priority
2 Bar 1
3 FooB 3
5 Baz 9
因为FooA,FooB和FooC根据SimilarArticles
表是相似的,并且FooB具有这三个记录中最高的priority
,所以只有FooB应该在结果集中(与Bar和Baz一起,没有类似的记录)。
答案 0 :(得分:0)
您需要执行左连接并过滤掉任何类似的文章。请参阅this great explanation排除使用SO创始人Jeff Atwood的LEFT JOIN。
react.js
如果您还希望获得与类似文章无关的最高优先级文章,那么您必须将此查询与该查询结合起来:
SELECT Articles.*
FROM Articles
LEFT JOIN SimilarArticles ON Articles.id = SimilarArticles.article_id
WHERE SimilarArticles.article_id IS NULL
ORDER BY priority DESC
注意:union之后的第二个查询将返回所有优先级最高的记录,而不仅仅是第一个。如果您真的只想返回第一个,那么您必须在该查询的末尾添加 SELECT *
FROM Articles
LEFT JOIN SimilarArticles ON Articles.id = SimilarArticles.article_id
WHERE SimilarArticles.article_id IS NULL
UNION ALL
SELECT Articles.*
FROM Articles
INNER JOIN SimilarArticles ON Articles.id = SimilarArticles.article_id
INNER JOIN (SELECT max(priority) AS priority FROM SimilarArticles) maxp
ON maxp.priority = Articles.priority
WHERE SimilarArticles.article_id IS NOT NULL
。
答案 1 :(得分:0)
我找到的一个工作解决方案是创建一个查询,该查询为我提供了每个文章的所有类似文章ID,这些文章在一个额外的列中以逗号分隔。
在我的服务器端语言中迭代结果时,我会爆炸类似的文章ID并构建一个包含所有类似ID的数组。这使我有可能跳过ID已经存储在该数组中的所有行。
虽然我更喜欢纯SQL的解决方案,但我觉得这在我的情况下运行得很好。
SELECT
id,
GROUP_CONCAT(
IF (sa.article_id = a.id, similar_article_id, article_id)
SEPARATOR ','
) AS similar_ids,
text,
priority
FROM Articles a
LEFT JOIN SimilarArticles sa
ON a.id = sa.article_id OR a.id = sa.similar_article_id
GROUP BY id
ORDER BY priority DESC
id similar_ids text priority
1 3,4 FooA 3
4 3,1 FooC 2 <- Will be skipped
2 NULL Bar 1
3 1,4 FooB 1 <- Will be skipped