La respuesta más cercana que puedo dar es esta
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
;
Entonces, ¿cómo funciona? Al principio seleccionamos 10k filas ordenadas aleatoriamente de elementos. Después, sumamos los precios de los artículos hasta llegar a 30 artículos con una suma inferior a 500. Cuando encontramos 30 artículos, repetimos el proceso hasta recorrer los 10k artículos seleccionados. Al encontrar estos 30 artículos, ahorramos la suma máxima encontrada. Entonces, al final, seleccionamos 30 artículos con la mayor suma (es decir, los 500 más cercanos al objetivo). No estoy seguro de si eso es lo que querías originalmente, pero encontrar el exacto la suma de 500 requeriría demasiado esfuerzo en el lado DB.