【问题标题】:How to normalize tags table如何规范化标签表
【发布时间】:2012-09-01 09:01:29
【问题描述】:

我有这样的桌子:

post:
+----------------+-----------+
| article_id     | tags      | 
+----------------+-----------+
| 1              |  x1,x2,x3| 
| 2              |  x1,x4,x5 | 
+----------------+-----------+

我想做的是对其进行规范化,所以我再创建 2 个表:

tags:
+----------------+-----------+
| tag_id         | tag_name  | 
+----------------+-----------+
| 1              |    x1     | 
| 2              |    x2     | 
| 3              |    x3     |
+----------------+-----------+

post_tag:
+----------------+-----------+
| id_post         | id_tag  | 
+----------------+-----------+
| 1              |    1     | 
| 1              |    2     | 
| 2              |    1     |
+----------------+-----------+

我已经将所有标签从 post 表导出到 tags 表,现在每个标签在 tags 表中都有自己的 id,但是当我在考虑如何使用 post_tag 表时我很困惑?

编辑:questin 是如何填充 post_tag 表,查询会是什么样子?

这样尝试过

$sql=mysql_query("SELECT * FROM post"); 
    while($row=mysql_fetch_array($sql)) {
        $article_id=$row['article_id'];
  $all_tags =$row['tags'];      
  $tags= explode(",",$all_tags);                                
    foreach($all_tags as $tag) {
     $sql2=mysql_query("SELECT * FROM tags WHERE tag_name = '$tag'");
      while($row=mysql_fetch_array($sql2)) {                               $tag_id=$row['tag_id'];                                  $q = "INSERT INTO post_tag (id_post, id_tag) VALUE ('$article_id', $tag_id')";
        $r = mysql_query($q);
      }
    }
}

但它没有写完整的 post_tag 表

【问题讨论】:

  • 这看起来不错..你在困惑什么?
  • 你有什么问题? post_tag 表很好
  • 您所拥有的是帖子和标签之间的 n 到 n 关系。您的 post_tag 表条目将充当一个标签和一篇文章之间的链接。像这样,您将一篇文章链接到 n 个标签,并将一个标签链接到 n 个文章。
  • @Eregrith:更常见的是使用 M 和 N,不同的字母
  • 我的意思是每边的关系都是0,n。

标签: php mysql database normalization


【解决方案1】:

也许这个可行?

$sql= mysql_query("SELECT * FROM post"); 
while($row=mysql_fetch_array($sql)) {
    $article_id=$row['article_id'];
    $all_tags = $row['tags'];      
    $tags = explode(",",$all_tags);              
    foreach($all_tags as $tag_title) {
        $tag_id = null;
        $tag=mysql_fetch_assoc(mysql_query('SELECT * FROM tags WHERE tag_name = "'.$tag_title.'"'));
        if ($tag) {
            $tag_id = $tag['tag_id']; 
        } else {
            mysql_query('INSERT INTO tags SET tag_name = "'.$tag_title.'"');
            $tag_id = mysql_insert_id();
        } 
        $q = "INSERT INTO post_tag (id_post, id_tag) VALUE ('$article_id', $tag_id')";
        $r = mysql_query($q);
    }
}

运行循环后,您需要删除 post 表中的旧列

【讨论】:

    【解决方案2】:

    对于帖子的每个标签,您在 post_tag 表中插入一个条目。这称为 m 对 n 关系。谷歌它;)

    • post_id: 1, tag_id: 1
    • post_id: 1, tag_id: 2
    • post_id: 1, tag_id: 3

    发帖

    • post_id

    标签

    • tag_id
    • 标签名称

    post_tag

    • post_id
    • tag_id

    【讨论】:

      【解决方案3】:

      我明白了,您想用一个 sql 查询来解决您的问题,但这并不方便。尝试使用php-power,你会成功的。

      php方式。 1.创建表tags和posts_tags(就像你在问题中描述的那样)。 2. 在 php 中获取当前post 表中的所有行并循环它:

      foreach($query_results as $row) {
        $article_id = $row['article_id];
        $tags = explode('|', $row['tags']);
        foreach($tags as $tag) {
          // here check if this tag exists in your new `tags` table (by tag's name). If it is, save its id in $tag_id variable.
          // if a tag don't exists then insert it. And put its new id (mysql returns it after inserting) into $tag_id.
          // After that add a row ($article_id, $tag_id) to table `posts_tags`
        }
      }
      

      然后从旧的post 表中删除列tags。利润!

      附言在tags 表中的标签名称和posts_tags 表中的对(article_id,tag_id)上创建唯一索引。

      【讨论】:

      • 你“描述”的部分正是让我困惑的地方,它是循环内循环,循环内循环,......
      • 这里只有两个循环。没关系。请注意,在这种情况下不需要优化,因为您执行该操作(重新创建数据库)一次。
      【解决方案4】:

      假设您有一个名为my cat! 的帖子,它的ID 为1。您希望在其中添加标签cats 和home。

      您应该首先在标签表中创建标签cats 和home(如果它们尚不存在)。假设他们是cats | 2 和home | 4(数字是他们的ID)。

      然后您需要在 post_tag 表中存储值 1 | 2 和 1 | 4,其中第一个值是帖子的 id,第二个值是标签的 id。

      要查找帖子编号 1 的标签,您需要类似

      SELECT Tags.name FROM Tags, Tags_Posts WHERE Tags_Posts.post_id = 1 AND Tags.id = Tags_Posts.tag_id

      【讨论】:

      • 这一切都清楚了,我明白了,但是我很困惑如何使用现有的数据库,mysql 查询应该是什么样子......如何填充 post_tag 表?
      • 谢谢 Ivo,但我正在尝试从现有帖子中填充 post_tag 表,标记表
      • 正如我所说,首先填充标签表,然后将值插入连接表,将标签 ID 与帖子 ID 链接起来。
      • 我不明白,查询会是什么样子?
      • 您发出两个INSERT 查询,第二个取决于第一个的结果(它需要id)。
      猜你喜欢
      • 1970-01-01
      • 2021-04-04
      • 2015-05-24
      • 2011-05-30
      • 2019-11-11
      • 2012-04-06
      • 1970-01-01
      • 2011-03-08
      • 1970-01-01
      相关资源
      最近更新 更多