[英]Difficult MySQL Update Query with Self-Join
我们的网站上有清单。 我们使用具有以下结构的连接表将我们的成员与这些各种清单连接起来:
CREATE TABLE `connections` (
`cid1` int(9) unsigned NOT NULL DEFAULT '0',
`cid2` int(9) unsigned NOT NULL DEFAULT '0',
`type` char(2) NOT NULL,
`created` datetime DEFAULT NULL,
`updated` datetime DEFAULT NULL,
PRIMARY KEY (`cid1`,`cid2`,`type`,`cid3`),
KEY `cid1` (`cid1`,`type`),
KEY `cid2` (`cid2`,`type`)
);
我们遇到的问题是,当我们不得不不时合并重复的列表时,我们还需要更新成员连接,并且一直在使用以下查询,如果一个成员同时连接到两个列表,该查询就会中断:
update connections set cid2=100000
where type IN ('MC','MT','MW') AND cid2=100001;
我不知道如何解决以下问题:
update connections set cid2=100000
where type IN ('MC','MT','MW') AND cid2=100001 AND cid1 NOT IN (
select cid1 from connections
where type IN ('MC','MT','MW') AND cid2=100000
);
当我尝试运行该查询时,出现以下错误:
ERROR 1093 (HY000): You can't specify target table 'connections' for update in FROM clause
这是一些示例数据。 请注意,cid1 = 10025925的更新冲突
+----------+--------+------+---------------------+---------------------+
| cid1 | cid2 | type | created | updated |
+----------+--------+------+---------------------+---------------------+
| 10010388 | 100000 | MC | 2010-08-05 18:04:51 | 2011-06-16 16:26:17 |
| 10025925 | 100000 | MC | 2010-10-31 09:21:25 | 2010-10-31 16:21:25 |
| 10027662 | 100000 | MC | 2011-06-13 16:31:12 | NULL |
| 10038375 | 100000 | MW | 2011-02-05 05:32:35 | 2011-02-05 19:51:58 |
| 10065771 | 100000 | MW | 2011-04-24 17:06:35 | NULL |
| 10025925 | 100001 | MC | 2010-10-31 09:21:45 | 2010-10-31 16:21:45 |
| 10034884 | 100001 | MC | 2011-01-20 18:54:51 | NULL |
| 10038375 | 100001 | MC | 2011-02-04 05:00:35 | NULL |
| 10041989 | 100001 | MC | 2011-02-26 09:33:18 | NULL |
| 10038259 | 100001 | MC | 2011-05-07 13:34:20 | NULL |
| 10027662 | 100001 | MC | 2011-06-13 16:33:54 | NULL |
| 10030855 | 100001 | MT | 2010-12-31 20:40:18 | NULL |
| 10038375 | 100001 | MT | 2011-02-04 05:00:36 | NULL |
+----------+--------+------+---------------------+---------------------+
我希望有人可以建议运行上述查询的正确方法。 提前致谢!
一种可能的方法是对子查询使用临时表,然后从临时表中选择。 但是,如果您需要执行许多此类查询,则效率可能会迅速下降。
create temporary table subq as select cid1 from connections where type IN ('MC','MT','MW') AND cid2=100000
和
update connections set cid2=100000 where type IN ('MC','MT','MW') AND cid2=100001 AND cid1 NOT IN (select cid1 from subq);
查询错误的原因是因为在MySQL中,您无法从试图在同一查询中进行更新的表中进行选择。
使用UPDATE IGNORE避免重复冲突。
我认为您应该尝试阅读INSERT ON DUPLICATE KEY。 这样的想法是,您对总是创建DUPLICATE冲突的INSERT查询进行构架,然后UPDATE部分将发挥其作用。
我在想类似以下内容的方法,但是我不确定100%之前和之后的数据如何确定准确性。 想法是在子查询的where
子句和排除cid1
不能匹配的where
将表自身连接起来。
update connections c1 left outer join connections c2
on (c2.cid2 = 100000 and c2.type in ('MC','MT','MW') and c1.cid1 != c2.cid1)
set c1.cid2 = 100000
where c1.type in ('MC', 'MT', 'MW') and c1.cid2=100001 and c2.cid1 is null;
据我所知,它将起作用。 我使用了您的create table
(减去主键中的cid3
),并确保我有2行具有相同的cid1
和不同的cid2
(一个为100000,另一个为100001),并且该语句仅影响了1行。
UPDATE connections cn1
LEFT JOIN connections cn2 ON cn1.cid1 != cn2.cid1
AND cn2.type IN ('MC','MT','MW')
AND cn2.cid2=100000
SET cn1.cid2=100000
WHERE cn1.TYPE IN ('MC','MT','MW')
AND cn1.cid2=100001
AND cn2.cid1 IS NULL -- i.e. there is no matching record
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.