我的网站上有文章,我想添加描述每篇文章的标签,但我在设计标签的 mysql 表时遇到问题。我有两个想法:

  1. 每篇文章都有“标签”字段,标签的格式为:“标签1,标签2,标签3”
  2. 创建其他名为标签的表,其中包含字段:标签名称、文章 ID

因此,当我想要 ID 为 1 的文章的标签时,我会运行

SELECT ... FROM tags WHERE `article_id`=1;

但是,我还想通过比较标签来了解 3 篇最相似的文章,所以如果我有一篇带有标签“php,mysql,erlang”的文章,以及 5 篇带有标签的文章:“php,mysql”,“erlang,ruby”,“php erlang”,“mysql,erlang,javascript”,我会选择1.,3.和 4.,因为这 3 个与主文章具有大多数相同的标签。

还有另一个问题,获得 10 个“最常用标签”的最佳方法是什么?

有帮助吗?

解决方案

一般来说,对于这种多对多关系,有三个表:

  • 这 ”article“ 桌子
    • 主键=id
  • 这 ”tag“ 桌子
    • 主键=id
    • 包含每个标签的数据:
      • 名称,例如
  • A ”tags_articles“表,充当连接表,仅包含:
    • id_article :指向一篇文章的外键
    • id_tag :指向标签的外键


这样,任何标签的数据就不会重复:对于每个标签,在 tag 桌子。

并且,对于每篇文章,您可以有多个标签(即中的几行 tags_articles 桌子) ;当然,对于每个标签,您可以有几篇文章。

按照这个想法,获取文章的标签列表只需进行额外的查询,例如:

select tag.*
from tag
    inner join tags_articles on tag.id = tags_articles.id_tag
where tags_articles.id_article = 123


获得三篇“最相似”的文章意味着:

  • 选择具有第一篇文章所具有标签的文章
  • 只使用那些具有最重要数量的相同标签的标签

未经测试,但一个想法可能如下所示:

select article.id, count(*) as nb_identical_tags
from article
    inner join tags_articles on tags_articles.id_article = article.id
    inner join tag on tag.id = tags_articles.id_tag
where tag.name in ('php', 'mysql', 'erlang')
      and article.id <> 123
group by article.id
order by count(*) desc
limit 3

基本上,你:

  • 为初始文章中出现的每个标签选择文章 ID
    • 因为存在内部联接,如果数据库中的一篇文章有​​ 2 个与 where 条款,没有 group by 子句,该文章将有两行
    • 当然,您不想重新选择已有的文章——这意味着它必须被排除。
  • 但是,当你使用 group by article.id, ,每篇文章只有一行
    • 但你可以使用 count, ,找出每篇文章与第一篇文章有​​多少个共同标签
  • 那么,只需按标签数量进行排序,并仅获取第三三行即可。

其他提示

首先,您需要使用 Pascal MARTIN 关于桌子设计的建议。

至于查找类似的文章,这里有一些可以帮助您入门的内容。假定 @article_id 是您要查找匹配项的文章,@tag1、@tag2、@tag3 是该文章的标签:

SELECT article_id, count(*)
FROM tags_articles
WHERE article_id <> @article_id
AND tag_id IN (@tag1, @tag2, @tag3)
GROUP BY article_id
ORDER BY count(*) DESC
LIMIT 3

是的,但是你没有回答我的主要问题,如何获得3篇最相似的文章?

回答:只需在合并表 (tags_articles) 中查找相同的标签 id 即可。收集它们并创建一个图案。

例如:第 1 条有标签:1,2第2条有标签:2,3,4 第5条有标签:6,7,2 第7条有标签:7,1,2,3

如果您想要第 1 篇文章中最相似的 3 篇文章,则必须查找标签 1,2。您会发现第 7 条最相似,第 2 条和第 5 条有一些相似之处。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top