Het beste antwoord dat ik kan geven is dit
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
;
Dus hoe werkt het? Eerst selecteren we 10k willekeurig geordende rijen uit items. Daarna tellen we de prijzen van artikelen op totdat we 30 artikelen hebben bereikt met een som van minder dan 500. Als we 30 artikelen hebben gevonden, herhalen we het proces totdat we alle 10.000 geselecteerde artikelen hebben doorlopen. Bij het vinden van deze 30 items besparen we maximaal gevonden som. Dus aan het einde selecteren we 30 items met de grootste som (d.w.z. het dichtst bij de beoogde 500). Ik weet niet zeker of dat is wat je oorspronkelijk wilde, maar het vinden van de exacte som van 500 zou te veel inspanning vergen aan DB-kant.