Najbliższa odpowiedź, jaką mogę udzielić, to
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
;
Więc jak to działa? Na początku wybieramy 10k losowo uporządkowanych wierszy z pozycji. Następnie sumujemy ceny przedmiotów, aż dojdziemy do 30 przedmiotów z sumą mniejszą niż 500. Po znalezieniu 30 przedmiotów powtarzamy proces, aż przejdziemy przez wszystkie 10k wybranych przedmiotów. Wyszukując te 30 pozycji, zapisujemy maksymalną znalezioną sumę. Na koniec wybieramy 30 pozycji o największej sumie (czyli najbliżej celu 500). Nie jestem pewien, czy tego pierwotnie chciałeś, ale znalezienie dokładnego suma 500 wymagałaby zbyt dużego wysiłku po stronie DB.