使用自连接进行困难的 MySQL 更新查询

发布于 2024-11-15 17:59:55 字数 2318 浏览 3 评论 0原文

我们的网站有列表。我们使用具有以下结构的连接表将我们的会员与这些不同的列表连接起来:

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                |
+----------+--------+------+---------------------+---------------------+

我希望有人可以建议运行上述查询的正确方法。提前致谢!

Our website has listings. We use a connections table with the following structure to connect our members with these various listings:

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`)
);

The problem we've run into is when we have to combine duplicate listings from time to time we also need to update our member connections and have been using the following query which breaks if a member is connected to both listings:

update connections set cid2=100000
where type IN ('MC','MT','MW') AND cid2=100001;

What I can't figure out is how to do the following which would solve this issue:

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
);

When I try to run that query I get the following error:

ERROR 1093 (HY000): You can't specify target table 'connections' for update in FROM clause

Here is some sample data. Notice the update conflict for 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                |
+----------+--------+------+---------------------+---------------------+

I'm hoping that someone can suggest the right way to run the above query. Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

江湖正好 2024-11-22 17:59:55

查询中出现错误的原因是因为在 MySQL 中,您无法从同一查询中尝试 UPDATE 的表中进行 SELECT。

使用 UPDATE IGNORE 避免重复冲突。

我认为你应该尝试阅读 INSERT ON DUPLICATE KEY 。这个想法是,您构建一个始终会产生 DUPLICATE 冲突的 INSERT 查询,然后 UPDATE 部分将发挥其作用。

The reason for the error in your query is because in MySQL you cannot SELECT from the table you are trying to UPDATE in the same query.

Use UPDATE IGNORE to avoid duplicate conflicts.

I think you should try reading INSERT ON DUPLICATE KEY. The idea is that you frame an INSERT query that always create a DUPLICATE conflict and then the UPDATE part will do its part.

洋洋洒洒 2024-11-22 17:59:55

一种可能的方法是为子查询使用临时表,然后从临时表中进行选择。但是,如果您需要执行大量此类查询,效率可能会很快下降。

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);

One possible way would be to use a temporary table for your subquery then select from the temp table. Efficiency could break down fast if you need to execute a lot of these queires though.

create temporary table subq as select cid1 from connections where type IN ('MC','MT','MW') AND cid2=100000

And

update connections set cid2=100000 where type IN ('MC','MT','MW') AND cid2=100001 AND cid1 NOT IN (select cid1 from subq);
茶色山野 2024-11-22 17:59:55
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
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
阳光下的泡沫是彩色的 2024-11-22 17:59:55

我在想类似以下的事情,但我不能 100% 确定您的数据在确定准确性之前和之后的样子。这个想法是在子查询的 where 子句中将表与其自身连接起来,并且排除 where cid1 不得匹配。

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;

据我所知,它会起作用。我使用了您的创建表(减去主键中的cid3)并确保我有两行具有相同的cid1和不同的cid2(一个为 100000,另一个为 100001)并且该语句仅影响 1 行。

I was thinking something like the following, but I'm not 100% sure how your data looks before and after to determine accuracy. The idea is to join the table to itself on your subquery's where clause and the exclusion where cid1 must not match.

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;

As near as I can tell, it'll work. I used your create table (minus the cid3 in the primary key) and made sure I had 2 rows with the same cid1 and different cid2 (one 100000 and the other as 100001) and that the statement only affected 1 row.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文