MySQL查找相关文章

时间:2011-01-17 19:39:40

标签: sql mysql

我正在尝试最多选择10篇相关文章,其中相关文章是与其他文章有3个或更多相同关键字的文章。

我的表格结构如下:

articles[id, title, content, time]
tags[id, tag]
articles_tags[article_id, tag_id]

我可以在一个查询中选择相关文章的ID和标题吗?

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:4)

@updated排除搜索过的文章本身!

沿着这些方向的东西

select *
from articles
inner join (
 select at2.article_id, COUNT(*) cnt
 from articles a
 inner join articles_tags at on at.article_id = a.id
 # find all matching tags to get the article ids
 inner join articles_tags at2 on at2.tag_id = at.tag_id
     and at2.article_id != at.article_id
 where a.id = 1234  # the base article to find matches for
 group by at2.article_id
 having count(*) >= 3  # at least 3 matching keywords
) matches on matches.article_id = articles.id
order by matches.cnt desc
limit 10;  # up to 10 matches required

答案 1 :(得分:4)

假设标题也是唯一的

SELECT fA.ID, fA.Title
from
   Articles bA,
   articles_tags bAT,
   articles_tags fAT,
   Articles fA
where 
   bA.title = 'some name'   AND
   bA.id = bAT.Article_Id   AND
   bAT.Tag_ID = fAT.Tag_ID    AND
   fAT.Article_ID = fA.ID  AND
   fA.title != 'some name'
GROUP BY 
    fA.ID, fA.Title
HAVING
   count(*) >= 3

在哪里排除'种子'文章

因为我并不关心我匹配的WHICH标签,只是我在3个标签上匹配,我只需要tag_id并完全避免连接到标签表。所以现在我加入多对多表来找到有重叠的文章。

问题在于文章将100%匹配,因此我们需要从结果中消除这一点。

您可以通过3种方式排除该记录。你可以在加入之前从表中过滤它,你可以让它脱离连接,或者你可以在完成后过滤它。

如果在开始加入之前消除它,那么你就没有获得太大的优势。你有数千或数百万篇文章而且你只是在消除1.我也相信这对于article_tag映射表的最佳索引没有用。

如果在连接过程中执行此操作,则不等式将阻止该子句成为索引扫描的一部分,并在索引扫描后应用为过滤器。

将article_tags上的索引视为(Tag_ID,Article_ID)。如果我在tag_id = tag_id上将索引加入到自身中,那么我将立即定义要处理的索引片段,方法是将索引遍历到我的“种子”文章中的每个tag_id。如果我添加子句article_id!= article_id,则不能使用索引来定义要处理的切片。这意味着它将作为过滤器应用。例如说我的第一个标签是“蓝色”。我走了索引,得到所有“BLUE”的文章。 (当然是ID)。说有50行。我们知道1是我的种子文章,49是匹配。如果我不包括不平等,我将包括所有50条记录并继续前进。如果我确实包含不等式,那么我必须检查50条记录中的每条记录,看看哪个是我的种子,哪些不是。下一个标签是“Jupiter”,它匹配20,000篇文章。我必须再次检查索引的那一片中的每一行以排除我的种子文章。在经历了这个2,5,20次之后(取决于该种子文章的标签),我现在有一套完全干净的文章来做COUNT(*)和HAVING。如果我不将不等式作为我的联接的一部分包括在内,而只是在分组后过滤SEED ID,那么我只在一个非常短的列表上执行一次该文件管理器。

答案 2 :(得分:0)

如果您可以编写查询来获取具有匹配项的记录ID,那么您当然可以使用相同的查询返回标题。如果您真正的问题是“我如何编写查询以返回匹配项?”,那么请说出来,我将编辑此答案,并提供更多详细信息。