Phương pháp sau dựa trên thực tế là các thuộc tính possessions
bảng có khóa chính và citizen_id
không phải là một phần của nó. Đây là ý tưởng:
-
Đặt tất cả các tham số của bản cập nhật (
citizen_id
vàgood_id
để lọc các giá trị mới củacitizen_id
và số hàng cần cập nhật) vào một số bộ nhớ, một bảng chuyên dụng, có thể là hoặc một bảng tạm thời. -
Gán số hàng cho
possessions
phân vùng các hàng trên(citizen_id, good_id)
, sau đó tham gia tập hợp hàng đã xếp hạng vào bảng tham số để lọc tập hợp đầy đủ ban đầu trêncitizen_id
vàgood_id
, cũng như số lượng hàng. -
Tham gia
possessions
và kết quả của phép nối trước trên các giá trị khóa chính và cập nhậtcitizen_id
với các giá trị mới.
Trong SQL của MySQL, phần trên có thể giống như sau:
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
là bảng chứa các giá trị tham số.
Truy vấn sử dụng một phương pháp đánh số hàng đã biết sử dụng các biến, được triển khai trong f
truy vấn con.
Tôi không có MySQL nên không thể kiểm tra điều này đúng cách từ quan điểm hiệu suất, nhưng ít nhất bạn có thể thấy từ bản trình diễn SQL Fiddle này
mà phương pháp hoạt động. (Câu lệnh UPDATE nằm trong tập lệnh lược đồ, vì SQL Fiddle không cho phép các câu lệnh sửa đổi dữ liệu trong tập lệnh bên phải cho MySQL. Phía bên phải chỉ trả về nội dung sau UPDATE của possessions
.)