简体   繁体   English

规范化数据库表“标签”

[英]Normalize database table “tags”

I have a table called tags with columns id , vid_id , name where id is a random id generated with md5(uniqid()); 我有一个名为tag的表,其vid_id idvid_idname ,其中id是使用md5(uniqid());生成的随机ID md5(uniqid()); vid_id is the id of the video that tag is associated with, and name is the tag name. vid_id是与标签关联的视频的ID,而name是标签名称。 If a video has 5 tags, they all get stored in the tags table. 如果视频具有5个标签,则它们都将存储在标签表中。 I realized lately this is a bad table design because I have many duplicate tags. 我最近意识到这是一个不好的表设计,因为我有很多重复的标签。 I created another table tag_map . 我创建了另一个表tag_map It has three columns id , vid_id , tag_id . 它具有三列idvid_idtag_id I want to basically implement the 'toxi' solution shown here http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html . 我想基本实现此处所示的“毒性”解决方案http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

What I want to do is somehow transfer the data over from tags to tag_map , delete the vid_id column in tags and delete any extra entries in tags so each tag_map entry is mapped to only one tag entry. 我想做的是以某种方式将数据从标签转移到tag_map ,删除标签中的vid_id列并删除标签中的任何其他条目,因此每个tag_map条目仅映射到一个标签条目。 Anyone know an efficient way to do this? 有人知道这样做的有效方法吗? I keep thinking: 我一直在想:

$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']));
}

but then I get confused when I try to think of how I am going to remove the extra tags in table tags and map each tag_map entry to only one tags entry. 但是当我想到如何删除表标签中的多余标签并将每个tag_map条目映射到一个标签条目时,我感到困惑。 Any advice would be greatly appreciated. 任何建议将不胜感激。

One thing you could do is set the vid_id and tag_id pair as the primary key in your new tag_map table. 您可以做的一件事是将vid_idtag_id对设置为新tag_map表中的主键。 That way, when you go through the algorithm you have listed above, duplicate map entries will not be created, but you'll still have one for each tag. 这样,当您遍历上面列出的算法时,将不会创建重复的地图条目,但每个标签仍然会有一个。 Then, you can run a query to delete duplicates in the tags table like this one: 然后,您可以运行查询以删除tags表中的重复项,如下所示:

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

If I understand your post, then what you're after is a "Junction table" or "join table." 如果我了解您的帖子,那么您所追求的就是“连接表”或“联接表”。 (Upon re-reading, yes, this is the "Toxi" solution you're referring to. Not sure where it got the name "Toxi" but whatever.) (重新阅读后,是的,这是您所指的“ Toxi”解决方案。不确定它在何处获得“ Toxi”的名称,但无论如何。)

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

You want to have a table that has exactly one row for a given video. 您想要一个表,其中给定视频的一行恰好有一行。 And another table that has exactly one row for each tag. 还有另一个表,每个表正好有一行。 Then you need a third table in between that has one row for every combination of video and tag. 然后,您需要一个介于两者之间的第三张表,用于视频和代码的每种组合都有一行。 That way, you can query the third join table for all of the videos that match a given tag, or all the tags that match a given video. 这样,您可以在第三个联接表中查询与给定标签匹配的所有视频,或与给定视频匹配的所有标签。

I would create a new table "tag" and a table "video_tag". 我将创建一个新表“ 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 )
    }
}

Then delete the old tag table. 然后删除旧标签表。 If you want, do some renaming of the new tag tables. 如果需要,请对新标签表进行一些重命名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM