2011-06-17 56 views
2

我们的网站有房源。我们使用一个连接表具有以下结构为我们的会员与这些不同的房源连接:使用自我加入困难的MySQL更新查询

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

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

回答

2

查询错误的原因是因为在MySQL中,您无法从表中选择您想要在相同查询中更新的表。

使用UPDATE IGNORE可避免重复冲突。

我想你应该尝试阅读INSERT ON DUPLICATE KEY。这个想法是你构建了一个始终创建DUPLICATE冲突的INSERT查询,然后UPDATE部分将完成其部分。

+0

有时最好的解决方案是简单的。我在update语句中添加了ignore,然后用旧的cid2删除了任何剩余的行。非常感谢你的帮助! – 2011-06-17 06:18:11

+0

我很开心,它为你工作:-) – Abhay 2011-06-17 07:40:30

2

一种可能的方法是使用临时表作为子查询,然后从临时表中选择。如果您需要执行大量这些队列,效率可能会快速下降。

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

我想类似下面的,但我不能100%确保您的数据之前和之后,以确定准确的外观。我们的想法是将您的子查询的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; 

据我所知,它会工作。我用你的create table(在主键中减去cid3),并确保我有2行与cid1cid2(一个100000和另一个100001)相同,并且该语句只影响1行。

+0

谢谢,但不幸的是它并没有这样做。我试图按照逻辑,似乎是正确的,但不知道问题是什么。由于某种原因,它似乎没有匹配正确的行(请参阅上面新添加的数据)。 – 2011-06-17 06:01:08

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

+1:你说得对,左外连接是必要的。 – 2011-06-17 03:02:43

+0

我知道这是超级大的,但是任何人都知道为什么左外连接在这里更好? – 2016-09-14 20:04:26