将关系id设置为相关表中具有最小id的关系id

时间:2016-09-05 16:18:00

标签: mysql sql-update

我有以下问题。 我有一组存储在数据库表中的帖子。每个用户都可以使用已存在于数据库中的标记标记其帖子,或创建新标记。

我有桌子:

post表:

id  content
1   test1

tags

id  name
1   tag1
2   tag1
3   tag2
4   tag2

post_tags表(非常小的子集,实际上有大约20000条记录)

post_id tag_id
1       2
1       4

现在由于我们没有注意到的错误,出现了以下问题:每当用户编辑他们的帖子时,更新都会创建新标签并将其与帖子相关联,而不是重新使用标签表中已有的标签(如果标签表中的name字段设置为唯一,我们本可以更早地发现错误,但事实并非如此,即使它应该是唯一的)。

现在,我们修复了导致此问题的问题,并且我打算删除所有创建的重复标记,但首先我需要将帖子重新关联到使用该名称创建的第一个标记(id会自动递增,因此数字较低意味着旧的创造)。

我尝试了以下查询:

UPDATE post_tags
SET tag_id=(
    SELECT min_id FROM (
        SELECT min(id) as min_id, name 
        FROM tags t 
        WHERE t.name=(
            SELECT name 
            FROM tags t2 
            WHERE t2.id=tag_id
        ) GROUP BY name
    ) as `inner`
);

然而,消息Unknown column 'tag_id' in 'where clause'失败了。通常我希望内部tag_id子句中的WHERE在更新之前引用tag_id(与UPDATE table SET value = value + 1工作方式相同)但在这种情况下它似乎不起作用。

我的预期结果是使post_tags表格如下所示:

post_id tag_id
1       1
1       3

这(在实践中)等同于以前的数据,因为tag_id字段引用与以前名称相同的标记。我们需要首先执行此操作,以便我们可以删除重复的标记名称并将名称列设置为唯一,以防止再次发生这种情况。

我的架构的示例SQL小提琴:http://sqlfiddle.com/#!9/1ff0b8 (由于错误,我无法添加更新)。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

这有效:

UPDATE post_tags pt
JOIN tags t ON pt.tag_id = t.id
JOIN (
  SELECT name, min(id) AS min_id
  FROM tags
  GROUP BY name
  ) p ON t.name = p.name
SET pt.tag_id = p.min_id;