【问题标题】:Normalize database table "tags"规范化数据库表“标签”
【发布时间】:2011-10-19 19:22:09
【问题描述】:

我有一个名为 tags 的表,其中包含 idvid_idname 列,其中 id 是使用 md5(uniqid()); 生成的随机 id,vid_id 是标签所在的视频的 id关联,name 是标签名称。如果一个视频有 5 个标签,它们都会存储在标签表中。我最近意识到这是一个糟糕的表格设计,因为我有很多重复的标签。我创建了另一个表 tag_map。它有三列idvid_idtag_id。我想基本上实现这里显示的“毒”解决方案http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

我想要做的是以某种方式将数据从 tags 转移到 tag_map,删除 tags 中的 vid_id 列并删除任何额外的标签中的条目,因此每个 tag_map 条目仅映射到一个标签条目。有人知道这样做的有效方法吗?我一直在想:

$sql = 'SELECT * FROM tags';
$stmt3 = $conn->prepare($sql);
$result=$stmt3->execute();
while ($row = $stmt3->fetch(PDO::FETCH_ASSOC)) {

$id=md5(uniqid());

    $sql = 'INSERT INTO tag_map VALUES (?,?,?)';
$insert = $conn->prepare($sql);
$result=$insert->execute(array($id,$row['vid_id'],$row['id']));
}

但是当我尝试考虑如何删除表 tags 中的额外标签并将每个 tag_map 条目仅映射到一个标签条目时,我感到困惑。任何建议将不胜感激。

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    如果我理解您的帖子,那么您所追求的是“连接表”或“连接表”。 (重读后,是的,这就是您所指的“Toxi”解决方案。不确定它的名称“Toxi”是从哪里来的。)

    http://en.wikipedia.org/wiki/Junction_table

    您希望有一个表格,其中只有一行用于给定视频。还有另一个表,每个标签只有一行。然后你需要第三个表格,其中每个视频和标签组合都有一行。这样,您可以查询与给定标签匹配的所有视频的第三个连接表,或与给定视频匹配的所有标签。

    我将创建一个新表“tag”和一个表“video_tag”。

    foreach ( video_record in the video table ) {
        existingTags = read in list of tags for video_record from existing_tags_table
        foreach ( tag in existingTags ) {
            newTag = read tag from new tag table
            if ( newTag == null ) {
                save tag in new table
                newTag.name = existing tag name
                newTag.id = id from save procedure above
            }
            save entry in video_tag( video.id, newTag.id )
        }
    }
    

    然后删除旧的标签表。如果需要,可以对新标签表进行一些重命名。

    【讨论】:

    • 我有一个连接表。该表是 tag_map,它连接了表标签和表视频。我遇到的问题是我之前没有连接表,所以我在标签中有所有这些条目。我必须了解如何组织我目前在标签中拥有的数据,并将其重新分配到 tag_map 中,以便结构能够正常运行。
    • 非常感谢您花时间帮助我 Marvo!
    • 做了一个调整,指出当您阅读现有标签时,您正在阅读它们以获取您刚刚阅读的视频记录。希望这个错误没有阻碍您。 (当然,您的旧模型在标签表中就有视频 ID,所以您可能已经猜到了。)祝您好运!
    【解决方案2】:

    您可以做的一件事是将vid_idtag_id 对设置为新tag_map 表中的主键。这样,当您执行上面列出的算法时,不会创建重复的映射条目,但每个标签仍然有一个。然后,您可以运行查询以删除 tags 表中的重复项,如下所示:

    DELETE FROM TAGS WHERE ID NOT IN (SELECT tag_id FROM TAG_MAP)
    

    【讨论】:

    • 感谢您的输入,但这不起作用。 vid_id 和 tag_id 在表 tag_map 中不是唯一的。同一视频可能有多个条目,tag_id 可用于将不同视频映射到同一标签。
    • 我想我想说的是 (vid_id, tag_id) 对应该是你的 tag_map 表的主键。这样,您仍然可以将相同的 tag_id 映射到不同的 vid_id,但它不允许在规范化期间插入重复的条目。我在自己的项目上做类似的事情。我可能在这里遗漏了一些东西:)
    猜你喜欢
    • 2021-04-04
    • 2016-06-06
    • 2015-02-15
    • 2011-05-30
    • 2012-09-01
    • 2011-04-18
    • 1970-01-01
    • 2012-10-08
    相关资源
    最近更新 更多