Il metodo seguente si basa sul fatto che i possessions
la tabella ha una chiave primaria e citizen_id
non ne fa parte. Ecco l'idea:
-
Metti tutti i parametri dell'aggiornamento (
citizen_id
egood_id
su cui filtrare, i nuovi valori dicitizen_id
e il numero di righe da aggiornare) in uno spazio di archiviazione, una tabella dedicata, forse, o una tabella temporanea. -
Assegna numeri di riga a
possessions
partizionamento delle righe su(citizen_id, good_id)
, quindi unisci il set di righe classificato alla tabella dei parametri per filtrare il set completo originale sucitizen_id
egood_id
, nonché il numero di righe. -
Unisciti a
possessions
e il risultato del precedente join sui valori della chiave primaria e aggiornacitizen_id
con i nuovi valori.
Nell'SQL di MySQL, quanto sopra potrebbe apparire così:
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
;
Il possessions_update
è la tabella contenente i valori dei parametri.
La query utilizza un metodo noto di numerazione delle righe che impiega variabili, implementato in f
sottoquery.
Non ho MySQL, quindi non posso testarlo correttamente dal punto di vista delle prestazioni, ma almeno puoi vedere da questa demo di SQL Fiddle
che il metodo funziona. (L'istruzione UPDATE è nello script dello schema, perché SQL Fiddle non consente istruzioni di modifica dei dati nello script sul lato destro per MySQL. Il lato destro restituisce semplicemente il contenuto post-UPDATE di possessions
.)