我试图选择最多10条相关文章,其中相关文章是与其他文章具有3个或更多相同关键字的文章。
我的表结构如下:
articles[id, title, content, time] tags[id, tag] articles_tags[article_id, tag_id]
我可以在一个查询中选择所有相关的文章ID和标题吗?
任何帮助是极大的赞赏。
假设标题也是唯一的
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条记录中的每条记录,以查看哪些是我的种子,哪些不是我的种子。下一个标签是“木星”,它匹配20,000条。再次,我必须检查索引的该切片中的每一行以排除我的种子文章。在经历了2,5,20次(取决于该种子文章的标签)之后,我现在有了一组完全干净的文章来进行COUNT(*)和HAVING处理。如果我不将不等式作为连接的一部分,而只是将SEED ID过滤掉,然后通过分组,那么我仅在很短的列表中执行一次该过滤器。