请查看以下SQLFiddle以供参考:http://sqlfiddle.com/#!2/f02ca/1
我有两张几乎一模一样的桌子。我想确定表数据之间的差异,用另一个表中的不同数据更新一个表。

table1
|| *id* || *some_id* || *timestamp* ||
||    1 ||         A ||       01:00 ||
||    2 ||         B ||       02:00 ||
||    3 ||         B ||       01:00 ||
||    4 ||         A ||       02:00 ||
||    5 ||         A ||       03:00 ||

table2
|| *id* || *some_id* ||
||    1 ||         B ||  <-- some_id is different than table1
||    2 ||         B ||
||    3 ||         B ||
||    4 ||         A ||
||    5 ||         B ||  <-- some_id is different than table1

所以我想用表2中的新some_id更新表1。我很容易找到这两张桌子的区别:
SELECT t2.id
FROM table2 t2
LEFT JOIN table1 t1 ON t1.id = t2.id
WHERE t2.some_id != t1.some_id

结果:
1, 5 (the id's of the table2 rows that have a different some_id).

我想我可以这样问:
UPDATE table1
SET some_id =
    (SELECT some_id FROM table2 WHERE id IN
        (SELECT t2.id
        FROM table2 t2
        LEFT JOIN table1 t1 ON t1.id = t2.id
        WHERE t2.some_id != t1.some_id ))

我以为这个查询会用table1中的新some_id更新table2,但只针对some_ids之间不同的行。但我得到了以下错误:
SQL Error (1093): You can't specify target table 'table1' for update in FROM clause

我走对了吗?如果是,我该如何解决这个问题?有没有更好或更有效的方法来实现这一点?
几句话:
重要的是,我不只是更新或插入从table2table1的所有内容,因为timestamp列。更新行时,该列将更新自身。我只想在table1中更新some_id的行是table2中不同的行。所以本质上,timestamp列是用来显示最后一次更改该行的时间。
重要的是,这是在尽可能少的查询中完成的,并且它们是有效的。在我这里的简单示例中,每个表只有5行,但实际上我的表有数千行。

最佳答案

您可能需要一个带有JOIN的更新:

UPDATE     table1 AS t1
INNER JOIN table2 AS t2
ON         t1.id = t2.id
SET        t1.some_id = t2.some_id
WHERE      t1.some_id != t2.some_id
;

join基本上与SELECT语句中的join相同,只是它不需要是外部join,因为据我所知,您只想更新ids匹配的行。
下面是这个查询的SQL Fiddle演示:http://sqlfiddle.com/#!2/58eb8/1

10-07 13:47
查看更多