2

私たちのウェブサイトにはリストがあります。次の構造の接続テーブルを使用して、メンバーをこれらのさまざまなリストに接続します。

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

誰かが上記のクエリを実行する正しい方法を提案できることを願っています。前もって感謝します!

4

4 に答える 4

2

クエリのエラーの理由は、MySQL では、同じクエリで UPDATE しようとしているテーブルから SELECT できないためです。

UPDATE IGNORE を使用して、競合の重複を回避します。

INSERT ON DUPLICATE KEY を読んでみてください。アイデアは、常に DUPLICATE 競合を作成する INSERT クエリを構成し、UPDATE 部分がその役割を果たすということです。

于 2011-06-17T04:07:08.940 に答える
2

考えられる方法の 1 つは、サブクエリに一時テーブルを使用し、一時テーブルから選択することです。ただし、これらのクエリを多数実行する必要がある場合は、効率がすぐに低下する可能性があります。

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);
于 2011-06-17T01:35:36.443 に答える
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マイナス)を使用し、同じ行と異なる行が2つあり(1つは100000、もう1つは100001)、ステートメントが1行にのみ影響することを確認しました。cid3cid1cid2

于 2011-06-17T02:27:50.693 に答える
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
于 2011-06-17T02:54:31.740 に答える