O método a seguir depende do fato de que as
possessions
tabela tem uma chave primária e citizen_id
não faz parte. Aqui está a ideia:-
Coloque todos os parâmetros da atualização (citizen_id
egood_id
para filtrar, os novos valores decitizen_id
e o número de linhas a serem atualizadas) em algum armazenamento, uma tabela dedicada, talvez, ou uma tabela temporária.
-
Atribuir números de linha apossessions
particionamento de linhas em(citizen_id, good_id)
, junte o conjunto de linhas classificadas à tabela de parâmetros para filtrar o conjunto completo original emcitizen_id
egood_id
, bem como o número de linhas.
-
Junte-se apossessions
e o resultado da junção anterior nos valores da chave primária e atualizecitizen_id
com os novos valores.
No SQL do MySQL, o acima pode ficar assim:
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
;
O
possessions_update
é a tabela que contém os valores dos parâmetros. A consulta usa um método conhecido de numeração de linha que emprega variáveis, que é implementada no
f
subconsulta. Eu não tenho MySQL, então não posso testar isso corretamente do ponto de vista do desempenho, mas pelo menos você pode ver em esta demonstração do SQL Fiddle que o método funciona. (A instrução UPDATE está no script de esquema, porque o SQL Fiddle não permite instruções de modificação de dados no script do lado direito do MySQL. O lado direito apenas retorna o conteúdo pós-UPDATE de
possessions
.)