Câu trả lời gần nhất mà tôi có thể cung cấp là đây
set @cnt = 0;
set @cursum = 0;
set @cntchanged = 0;
set @uqid = 1;
set @maxsumid = 1;
set @maxsum = 0;
select
t.id,
t.name,
t.cnt
from (
select
id + 0 * if(@cnt = 30, (if(@cursum > @maxsum, (@maxsum := @cursum) + (@maxsumid := @uqid), 0)) + (@cnt := 0) + (@cursum := 0) + (@uqid := @uqid + 1), 0) id,
name,
@uqid uniq_id,
@cursum := if(@cursum + price <= 500, @cursum + price + 0 * (@cntchanged := 1) + 0 * (@cnt := @cnt + 1), @cursum + 0 * (@cntchanged := 0)) as cursum, if(@cntchanged, @cnt, 0) as cnt
from (select id, name, price from items order by rand() limit 10000) as orig
) as t
where t.cnt > 0 and t.uniq_id = @maxsumid
;
Vậy nó hoạt động như thế nào? Lúc đầu, chúng tôi chọn 10k hàng được đặt hàng ngẫu nhiên từ các mặt hàng. Sau đó, chúng tôi tổng hợp giá của các mặt hàng cho đến khi đạt được 30 mặt hàng có tổng nhỏ hơn 500. Khi chúng ta tìm thấy 30 mặt hàng, chúng ta lặp lại quy trình cho đến khi xem hết 10k mặt hàng đã chọn. Trong khi tìm 30 mục này, chúng tôi tiết kiệm tối đa tổng số tiền tìm được. Vì vậy, cuối cùng, chúng tôi chọn 30 mục có tổng lớn nhất (nghĩa là gần nhất với mục tiêu 500). Không chắc đó có phải là điều bạn muốn ban đầu hay không, nhưng tìm chính xác tổng 500 sẽ đòi hỏi quá nhiều nỗ lực từ phía DB.