web-dev-qa-db-ja.com

LEFT JOINを使用してMySQLの複数のテーブルを更新する

2つのテーブルがあり、LEFT JOINのすべての行のT1のフィールドを更新したい。

簡単な例として、次の結果セットのすべての行を更新します。

SELECT T1.* FROM T1 LEFT JOIN T2 ON T1.id = T2.id WHERE T2.id IS NULL  

MySQLマニュアル は次のように述べています:

複数テーブルのUPDATEステートメントでは、LEFT JOINなど、SELECTステートメントで許可されている任意のタイプの結合を使用できます。

しかし、文書化された複数テーブルの更新では、それを行うための適切な構文が見つかりません。

適切な構文は何ですか?

157
Paul Oyster
UPDATE  t1
LEFT JOIN
        t2
ON      t2.id = t1.id
SET     t1.col1 = newvalue
WHERE   t2.id IS NULL

SELECTの場合、NOT IN/NOT EXISTS構文を使用する方が効率的です。

SELECT  t1.*
FROM    t1
WHERE   t1.id NOT IN
        (
        SELECT  id
        FROM    t2
        )

パフォーマンスの詳細については、私のブログの記事を参照してください。

残念ながら、MySQLでは、UPDATEステートメントのサブクエリでターゲットテーブルを使用できません。そのため、効率の低いLEFT JOIN構文に固執する必要があります。

293
Quassnoi

同じことがデータが正規化されたシナリオにも適用できますが、今度は3番目のテーブルで見つかった値を持つテーブルが必要です。以下を使用すると、2番目のテーブルに好かれる3番目のテーブルの情報でテーブルを更新できます。

UPDATE t1
LEFT JOIN
 t2
ON 
 t2.some_id = t1.some_id
LEFT JOIN
 t3 
ON
 t2.t3_id = t3.id
SET 
 t1.new_column = t3.column;

これは、ユーザーとグループがあり、ユーザーにグループ名の独自のバリエーションを追加できるようにしたい場合に役立ちます。そのため、元々、ユーザーがいるフィールドに既存のグループ名をインポートする必要があります。変更できるようになります。

26
theprivileges
Table A 
+--------+-----------+
| A-num  | text      | 
|    1   |           |
|    2   |           |
|    3   |           |
|    4   |           |
|    5   |           |
+--------+-----------+

Table B
+------+------+--------------+
| B-num|  date        |  A-num | 
|  22  |  01.08.2003  |     2  |
|  23  |  02.08.2003  |     2  | 
|  24  |  03.08.2003  |     1  |
|  25  |  04.08.2003  |     4  |
|  26  |  05.03.2003  |     4  |

テーブルAのフィールドテキストを更新します

UPDATE `Table A`,`Table B`
SET `Table A`.`text`=concat_ws('',`Table A`.`text`,`Table B`.`B-num`," from                                           
",`Table B`.`date`,'/')
WHERE `Table A`.`A-num` = `Table B`.`A-num`

そして、この結果に来ます:

Table A 
+--------+------------------------+
| A-num  | text                   | 
|    1   |  24 from 03 08 2003 /  |
|    2   |  22 from 01 08 2003 /  |       
|    3   |                        |
|    4   |  25 from 04 08 2003 /  |
|    5   |                        |
--------+-------------------------+

ここでは、表Bの1つのフィールドのみが受け入れられますが、この結果になります。

Table A 
+--------+--------------------------------------------+
| A-num  | text                                       | 
|    1   |  24 from 03 08 2003                        |
|    2   |  22 from 01 08 2003 / 23 from 02 08 2003 / |       
|    3   |                                            |
|    4   |  25 from 04 08 2003 / 26 from 05 03 2003 / |
|    5   |                                            |
+--------+--------------------------------------------+
4
DNS
UPDATE `Table A` a
SET a.`text`=(
        SELECT group_concat(b.`B-num`,' from ',b.`date` SEPARATOR ' / ') 
        FROM `Table B` b WHERE (a.`A-num`=b.`A-num`)
)
0
guest