Den følgende metode er afhængig af, at possessions
tabel har en primær nøgle og citizen_id
er ikke en del af det. Her er ideen:
-
Indsæt alle parametrene for opdateringen (
citizen_id
oggood_id
at filtrere på, de nye værdier afcitizen_id
og antallet af rækker, der skal opdateres) i et eller andet lager, måske en dedikeret tabel eller en midlertidig tabel. -
Tildel rækkenumre til
possessions
rækker partitionering på(citizen_id, good_id)
, og tilslut derefter det rangerede rækkesæt til parametertabellen for at filtrere det originale fulde sæt påcitizen_id
oggood_id
, samt antallet af rækker. -
Deltag i
possessions
og resultatet af den forrige join på de primære nøgleværdier og opdaterecitizen_id
med de nye værdier.
I MySQL's SQL kan ovenstående se sådan ud:
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
;
possessions_update
er tabellen, der indeholder parameterværdierne.
Forespørgslen bruger en kendt metode til rækkenummerering, der anvender variabler, som er implementeret i f
underforespørgsel.
Jeg har ikke MySQL, så jeg kan ikke teste dette ordentligt fra ydeevnesynspunktet, men du kan i det mindste se fra denne SQL Fiddle-demo
at metoden virker. (UPDATE-sætningen er i skemascriptet, fordi SQL Fiddle ikke tillader datamodifikationssætninger i højreside-scriptet til MySQL. Den højre side returnerer bare post-UPDATE-indholdet af possessions
.)