Рекламная система Советы

Я создаю рекламную систему, которая чаще показывает объявления, предлагающие самую высокую цену.

Вот пример структуры таблицы, которую я использую, но упрощенной …

+----+----------+------------------------+----------------------+-----+
| id | name     | image                  | destination          | bid |
+----+----------+------------------------+----------------------+-----+
| 1  | abc, co  | htt.../blah            | htt...djkd.com/      | 3   |
+----+----------+------------------------+----------------------+-----+
| 2  | facebook | htt.../blah            | htt...djkd.com/      | 200 |
+----+----------+------------------------+----------------------+-----+
| 3  | google   | htt.../blah            | htt...djkd.com/      | 78  |
+----+----------+------------------------+----------------------+-----+

Сейчас, прямо сейчас я выбираю значения из базы данных, а затем вставляю их в массив и выбираю случайным образом, как показано ниже:

$ads_array = [];
$ads = Ad::where("active", "=", 1)->orderBy("price", "DESC");

if ($ads->count() > 0) {
$current = 0;
foreach ($ads->get() as $ad) {
for ($i = 0; $i <= ($ad->price == 0 ? 1 : $ad->price); $i++) {
$ads_array[$current] = $ad->id;
$current++;
}
}

$random = rand(0,$current-1);
$ad = Ad::where("id", "=", $ads_array[$random])->first();

...
}

Итак, по сути, это то, что он вставляет идентификатор объявления в массив 1*$bid раз. К сожалению, это очень неэффективно (по очевидным причинам), но это был лучший способ сделать это.

Есть ли лучший способ выбрать случайное объявление из моей базы данных; в то же время давая более высокую цену более высокую вероятность быть показанным?

3

Решение

Похоже, что это может помочь (но вся заслуга в этом парень в комментариях)

SELECT ads.*
FROM ads
ORDER BY -log(1.0 - rand()) / ads.bid
LIMIT 1

Скрипт для проверки этого:

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;', 'test', 'test');$times = array();

// repeat a lot to have real values
for ($i = 0; $i < 10000; $i++) {
$stmt = $pdo->query('SELECT ads.* FROM ads ORDER BY -log(1.0 - rand()) / bid LIMIT 1');
$bid = $stmt->fetch()['bid'];
if (isset($times[$bid])) {
$times[$bid] += 1;
} else {
$times[$bid] = 1;
}
}

// echoes the number of times one bid is represented
var_dump($times);

Цифры, которые приходят ко мне из этого теста, довольно хороши:

// key is the bid, value is the number of times this bid is represented
array (size=3)
200 => int 7106
78 => int 2772
3 => int 122

Дальнейшая ссылка на математическое объяснение

Многие важные одномерные распределения могут быть выбраны путем инверсии с использованием простых выражений в замкнутой форме. Некоторые из наиболее полезных из них перечислены здесь.

Пример 4.1 (Экспоненциальное распределение). Стандартное экспоненциальное распределение имеет плотность f (x) = e − x на x> 0. Если X имеет это распределение, то E (X) = 1, и мы пишем X ∼ Exp (1). Кумулятивная функция распределения: F (x) = P (X x) = 1-e-x, причем F-1 (u) = -log (1-u). Поэтому, принимая X = — log (1 — U) для U ∼ U (0, 1), генерирует стандартные экспоненциальные случайные величины. Дополнительная инверсия использует X = — log (U).

Экспоненциальное распределение со скоростью λ> 0 (и средним θ = 1 / λ) имеет PDF λexp (−λx) для 0 �� x < ∞. Если X имеет это распределение, то мы пишем X ∼ Exp (1) / λ или, что эквивалентно, X ∼ θExp (1), в зависимости от того, сформулирована ли задача более естественно в терминах скорости λ или среднего θ. Мы можем сгенерировать X, взяв X = — log (1 — U) / λ.

приходящий из http://statweb.stanford.edu/~owen/mc/Ch-nonunifrng.pdf

3

Другие решения

Других решений пока нет …