2013-07-24 46 views
0

我已经在MySQL以下结构,表 'images_tags':MySQL查询的重新分配中的图片标签和避免重复

id | image_id | tag_id 
---------------------- 
1 | 243  | 52 
2 | 94  | 52 
3 | 56  | 52 
4 | 56  | 53 
5 | 56  | 54 

表 '标签':

id | tag  
--------------- 
52 | fashion 
53 | cars 
54 | sports 
55 | bikes 

我建立一个在我的CMS中删除一个标签,因为我需要将包含该标签的所有图片重新分配给另一个标签。问题是图片已经可以分配新的标签,我想避免可能的重复记录。

我无法找到正确的方式做直SQL所以我在PHP尝试如下:

$result=mysql_query("select image_id from images_tags where tag_id='".$oldtag."'"); 
while($row=mysql_fetch_assoc($result)){ 

    $result2=mysql_query("select id from images_tags 
    where image_id='".$row['image_id']."' and tag_id='".$newtag."'"); 

    if(mysql_num_rows($result2)==0){ 

     mysql_query("update images_tags set tag_id='".$newtag."' 
     where image_id='".$row['image_id']."' and tag_id='".$newtag."'"); 

    } 

} 

正如你看到的,我的代码是非常糟糕的和非有效,因为我跑在迭代中查询。你知道更好的方法来做到这一点吗?最好只在一个SQL查询中。谢谢。

+1

你应该在'image_id'和'tag_id'上有一个复合唯一键。 – ceejayoz

+0

'$ row ['id']'应该是'$ row ['image_id']'? '$ newtag'从哪里来? – Barmar

+0

抱歉写错问题。固定。 –

回答

1

当我想到这个问题时,我更容易想到“插入新的图像标签,如果合适,然后删除旧的”。

下面的代码采用这种方法:

create unique index image_tags_unique on image_tags(image_id, tag_id); 

insert into image_tags 
    select image_id, <newtagid> 
    from image_tags 
    where tag_id = <oldtagid> 
    on duplicate key ignore; 

delete from image_tags 
    where tag_id = <oldtagid>; 

第一步上image_tags创建一个唯一的索引,所以重复未在表允许的。

第二次插入新记录,忽略由重复生成的任何错误。

第三个删除旧记录。

说实话,你也可以用ignore关键字update而不是insert步骤做到这一点。然而,ignore是非常普遍的,因此 - 理论上 - 可能会有另一个错误被错误地忽略。 on duplicate key ignore关于什么是允许的更具体。

+0

不是关于如何挑选''的问题吗? – Barmar

+0

@Barmar。 。 。我不这么认为。这是一个引用:“问题是图片已经可以分配新标签,我想避免可能重复的记录。” –

+0

为了避免重复的记录,他需要选择一个与已经存在的不匹配的新标签。否则,当他删除旧标签时,他将完全失去该记录。 – Barmar

0

我认为这会将新行添加到符合条件的images_tags

insert into images_tags (image_id, tag_id) 
select image_id, tag_id 
from (select i.image_id image_id, t.id tag_id 
     from images_tags i 
     join tags t 
     where i.tag_id = $oldtag and t.id != $oldtag) crossp 
left join images_tags existing 
using (image_id, tag_id) 
where existing.id is null 
group by image_id 

crossp子查询产生的所有目前拥有的旧标签的image_ids,和所有比老标签其他标签之间的全跨产品。然后,我们对现有的images_tags执行左连接,并使用null检查来筛选出已存在的所有对。这会生成不匹配数据库中任何内容的image_idtag_id对的列表。最后,我们按image_id进行分组,因此我们只为每个图像添加一行。

完成此操作后,可以使用tag_id = $oldtag删除行。

SQLFIDDLE

与此唯一的问题是,它改变了images_tags行的ID。有一种方法可以通过UPDATE查询一步完成,但这不会造成这个问题,但我不知道如何将查询转化为该查询。