sql - MySQL 查找相关文章

标签 sql mysql

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

我的表结构如下:

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

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

非常感谢任何帮助。

最佳答案

假设title也是唯一的

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

在哪里排除“种子”文章

因为我不在乎我到底匹配了哪些标签,只关心我匹配了 3 个标签,所以我只需要 tag_id 并完全避免连接到标签表。所以现在我将多对多表连接到自身以查找有重叠的文章。

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

您可以通过 3 种方式排除该记录。您可以在加入之前从表中筛选它,可以让它从联接中删除,或者您可以在完成时筛选它。

如果您在开始连接之前将其删除,您将不会获得太多优势。您有数千或数百万篇文章,而您只消除了 1 篇。我还相信,根据 article_tag 映射表的最佳索引,这不会有用。

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

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

关于sql - MySQL 查找相关文章,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4717093/

相关文章:

sql - Postgres : SELECT column name based on Boolean value

SQL Oracle : Replace an empty result with word

java - springframework.jdbc.UncategorizedSQLException :Invalid column type- 错误

MySQL触发器将A表中的记录插入到B表中

php - Laravel 在提交表单而无需输入密码时在数据库中插入随 secret 码

sql - 如何在 Postgres 的不同行中连接字符串

sql - 在 Informix DB 中将字符串转换为日期

mysql - 将 plsql 函数的值复制到新表中

Mysql 查询还必须显示没有投票的帖子

mysql - Magnolia CMS seamingly 忽略 mysql 数据库但不使用 derby