La méthode suivante repose sur le fait que les possessions
la table a une clé primaire et citizen_id
n'en fait pas partie. Voici l'idée :
-
Mettez tous les paramètres de la mise à jour (
citizen_id
etgood_id
pour filtrer, les nouvelles valeurs decitizen_id
et le nombre de lignes à mettre à jour) dans un stockage, une table dédiée, peut-être, ou une table temporaire. -
Attribuez des numéros de ligne aux
possessions
partitionnement des lignes sur(citizen_id, good_id)
, puis joignez l'ensemble de lignes classé à la table de paramètres pour filtrer l'ensemble complet d'origine surcitizen_id
etgood_id
, ainsi que le nombre de lignes. -
Rejoindre les
possessions
et le résultat de la jointure précédente sur les valeurs de clé primaire et mettre à jourcitizen_id
avec les nouvelles valeurs.
Dans le SQL de MySQL, ce qui précède pourrait ressembler à ceci :
UPDATE possessions AS p
INNER JOIN
(
SELECT
@r := @r * (@c = p.citizen_id AND @g = p.good_id) + 1 AS r,
p.possession_id,
@c := p.citizen_id AS citizen_id,
@g := p.good_id AS good_id
FROM
possessions AS p
CROSS JOIN
(SELECT @r := 0, @c := 0, @g := 0) AS x
ORDER BY
p.citizen_id,
p.good_id
) AS f ON p.possession_id = f.possession_id
INNER JOIN
possession_updates AS u ON u.citizen_id = f.citizen_id AND u.good_id = f.good_id
SET
p.citizen_id = u.new_citizen_id
WHERE
f.r <= u.row_count
;
La possessions_update
est le tableau contenant les valeurs des paramètres.
La requête utilise une méthode connue de numérotation des lignes qui utilise des variables, qui est implémentée dans le f
sous-requête.
Je n'ai pas MySQL donc je ne peux pas tester cela correctement du point de vue des performances, mais au moins vous pouvez voir à partir de cette démo SQL Fiddle
que la méthode fonctionne. (L'instruction UPDATE se trouve dans le script de schéma, car SQL Fiddle n'autorise pas les instructions de modification de données dans le script de droite pour MySQL. Le côté droit renvoie simplement le contenu post-UPDATE de possessions
.)