我有一个名为标记的表格,列id
,vid_id
,name
其中id是使用md5(uniqid());
生成的随机ID vid_id是标记与之关联的视频的ID,name是标记名称。如果视频有5个标签,则它们都存储在标签表中。我最近意识到这是一个糟糕的表设计,因为我有许多重复的标签。我创建了另一个表 tag_map 。它有三列id
,vid_id
,tag_id
。我想基本上实现这里显示的'toxi'解决方案http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html。
我想要做的是以某种方式将数据从标记传输到 tag_map ,删除标记中的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']));
}
但是当我想到如何删除表标签中的额外标签并将每个tag_map条目映射到一个标签条目时,我感到困惑。任何建议都将不胜感激。
答案 0 :(得分:2)
您可以做的一件事是将vid_id
和tag_id
对设置为新tag_map
表中的主键。这样,当您浏览上面列出的算法时,将不会创建重复的地图条目,但您仍然会为每个标记创建一个。然后,您可以运行查询以删除tags
表中的重复项,如下所示:
DELETE FROM TAGS WHERE ID NOT IN (SELECT tag_id FROM TAG_MAP)
答案 1 :(得分:2)
如果我理解你的帖子,那么你所追求的是一个“连接表”或“连接表”。 (重新阅读,是的,这是你所指的“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 )
}
}
然后删除旧标签表。如果需要,可以重新命名新的标记表。