Най-близкият отговор, който мога да дам, е този
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
;
И така, как работи? Първо избираме 10k произволно подредени реда от артикули. След това сумираме цените на артикулите, докато достигнем 30 артикула със сума по-малка от 500. Когато намерим 30 артикула, повтаряме процеса, докато преминем през всичките 10k избрани артикула. Докато намираме тези 30 артикула, ние спестяваме максималната намерена сума. Така че в края избираме 30 артикула с най-голяма сума (което означава най-близката до целта 500). Не съм сигурен дали това е това, което първоначално искахте, но намираме точния сумата от 500 ще изисква твърде много усилия от страна на DB.