Mysql
 sql >> Base de données >  >> RDS >> Mysql

Étapes internes de mise à jour des jointures MYSQL

Pour la "requête ne mettant pas à jour correctement les lignes" :

Vous souhaitez mettre à jour la colonne b au minimum de b pour toutes les lignes ayant le même a

Vous avez proposé d'utiliser le JOIN suivant pour faire ça :

UPDATE test.tem t1
  JOIN test.tem t2
    ON t1.a = t2.a
SET t1.b = t2.b
WHERE t1.b > t2.b
     OR t1.b IS NULL;

Contrairement à ce que vous pourriez penser, ce JOIN n'effectuera pas de JOIN 1-1 . Il s'agit en fait d'un JOIN plusieurs-à-plusieurs depuis comme je l'ai dit hier vous n'utilisez pas de clé primaire (ni de clé unique non nulle) dans votre clause de jointure.

En fait, réécrire cette requête en tant que SELECT vous aidera probablement à comprendre le problème :

SELECT t1.a as t1a, t1.b as t1b, t2.a as t2a,t2.b as t2b FROM tem t1 JOIN tem t2
    ON t1.a = t2.a
WHERE t1.b > t2.b
     OR t1.b IS NULL;

+------+---------+------+--------+
| T1A  |  T1B    | T2A  |  T2B   |
+------+---------+------+--------+
|   1  | (null)  |   1  | 2      |
|   1  | 2       |   1  | 1      |
|   1  | (null)  |   1  | 1      |
|   1  | (null)  |   1  | (null) |
+------+---------+------+--------+

http://sqlfiddle.com/#!2/856a7/8

Comme vous le verrez maintenant, la ligne (1, null) correspondre à (1, 1) , (1, 2) et (1, null) . Selon l'ordre (non déterministe) d'exécution de la requête, cela peut affecter l'une des trois valeurs possibles pour b (je n'en suis pas sûr, mais peut-être même en en mettant à jour plusieurs fois). Dans une certaine mesure, vous avez eu de la chance de trouver le "mauvais" résultat lors du test !

J'espère que cela explique un peu plus pourquoi votre requête ne produit pas le résultat attendu. Depuis multi-table UPDATE les instructions n'autorisent pas ORDER BY ni GROUP BY clauses, quant à moi, pour trouver le "bon" résultat, je ne vois pas beaucoup d'autres options que de trouver le minimum d'abord via une sous-requête...