web-dev-qa-db-fra.com

UPDATE plusieurs tables dans MySQL en utilisant LEFT JOIN

J'ai deux tables et je veux mettre à jour les champs dans T1 pour toutes les lignes d'un LEFT JOIN.

Pour un exemple simple, mettez à jour toutes les lignes de l'ensemble de résultats suivant:

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

Le manuel MySQL indique que:

Les instructions UPDATE à tables multiples peuvent utiliser tout type de jointure autorisée dans les instructions SELECT, telles que LEFT JOIN.

Mais je ne trouve pas la syntaxe appropriée pour cela dans la documentation UPDATE à tables multiples documentée.

Quelle est la syntaxe appropriée?

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

Notez que pour un SELECT il serait plus efficace d'utiliser la syntaxe NOT IN/NOT EXISTS:

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

Voir l'article sur mon blog pour plus de détails sur les performances:

Malheureusement, MySQL ne permet pas d'utiliser la table cible dans une sous-requête dans une instruction UPDATE. C'est pourquoi vous devrez vous en tenir à la syntaxe moins efficace LEFT JOIN.

297
Quassnoi

La même chose peut être appliquée à un scénario où les données ont été normalisées, mais maintenant vous voulez que les valeurs d'une table soient trouvées dans une troisième table. Ce qui suit vous permettra de mettre à jour une table avec les informations d'une troisième table qui est appréciée par une deuxième table.

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;

Cela serait utile dans le cas où vous auriez des utilisateurs et des groupes et que vous souhaitiez qu'un utilisateur puisse ajouter sa propre variante du nom du groupe. Par conséquent, vous voudriez à l'origine importer les noms de groupes existants dans le champ où se trouve l'utilisateur. va pouvoir le modifier.

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  |

Je mettrai à jour le texte de champ dans le tableau A avec

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`

et arriver à ce résultat:

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

où un seul champ de la table B est accepté, mais je vais arriver à ce résultat:

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
Dinesh Rabara
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