The performance and the "randomness" of the result set can be further improved if you first define how many products to include.
$min = 10;
$max = 20;
$total = rand($min,$max);
The algorithm is based on the following:
In a collection of n positive numbers that sum up to S, at least one of them will be less than S divided by n (S/n)
Steps:
- Select a product randomly where price < BUDGET /TOTAL. Get its price, lets say X.
- Select a product randomly where price < (BUDGET - X)/(TOTAL - 1). Get its price, assume Y.
- Select a product randomly where price < (BUDGET - X - Y)/(TOTAL - 2).
Repeat this and get (TOTAL - 1) products. For the last product, select one where price = remaining price. (or price <= remaining price and order by price desc and hopefully you could get close enough).
$budget = 100;
$spent = 0;
$finished = false;
for($i = 0; $i < $total - 1; $i++) {
$getRandomProduct = mysql_query('SELECT `id`, `price` FROM `products` WHERE `price` <= "'.(($budget-$spent)/($total - $i)).'" ORDER BY RAND() LIMIT 1');
if(mysql_num_rows($getRandomProduct)) {
$randomProduct = mysql_fetch_assoc($getRandomProduct);
$productList[] = $randomProduct['id'];
$spent += $randomProduct['price'];
} else {
break;
}
}
$getRandomProduct = mysql_query('SELECT `id`, `price` FROM `products` WHERE `price` <= "'.($budget-$spent).'" ORDER BY `price` DESC LIMIT 1');
$productList[] = $randomProduct['id'];
This improves:
- The query performance, the condition is more strict
- The result set is more random, as previous you could easily select the 1st product close to the budge and limit the budget of the others
References:
My answer using the same algorithm for another question