У меня есть несколько записей в моей базе данных, в моем случае видео с рейтингом и популярностью и другими факторами. Из всех этих факторов я рассчитываю фактор вероятности или больше, чтобы сказать фактор повышения.
Таким образом, у меня, по сути, есть поля ID и BOOST. Повышение рассчитывается таким образом, что оно получается как целое число, представляющее процент того, как часто эта запись должна попадать в сравнении.
ID Boost
1 1
2 2
3 7
Так что, если я запускаю свою произвольную функцию бесконечно, у меня должно получиться Х попаданий по ИД 1, вдвое больше по ИД 2 и в 7 раз больше по ИД 3.
Таким образом, каждое попадание должно быть случайным, но с вероятностью (boost / sum of boosts)
. Таким образом, вероятность для идентификатора 3 в этом примере должна быть 0,7 (потому что сумма равна 10. Я выбираю эти значения для простоты).
Я думал о чем-то вроде следующего запроса:
SELECT id FROM table WHERE CEIL(RAND() * MAX(boost)) >= boost ORDER BY rand();
К сожалению, это не работает, после рассмотрения следующих записей в таблице:
ID Boost
1 1
2 2
С вероятностью 50/50 будет случайным образом выбирать только 2-й или оба элемента.
Таким образом, 0,5 попадания переходит ко второму элементу.
И 0,5 попадания идет к (второму и первому) элементу, который выбирается случайным образом, так что каждый по 0,25.
Таким образом, мы получаем соотношение 0,25 / 0,75, но оно должно быть 0,33 / 0,66
Мне нужна какая-то модификация или новый метод, чтобы сделать это с хорошей производительностью.
Я также подумал о накопительном увеличении поля накопления, поэтому я просто делаю запрос диапазона из (0-sum()
), но тогда мне придется переиндексировать все, что идет после одного элемента, если я изменю его или разработаю какой-нибудь алгоритм обмена что-то ... но это действительно не элегантно и прочее.
Как вставка / обновление, так и выбор должны быть быстрыми!
Есть ли у вас какие-либо решения этой проблемы?
Лучший вариант использования - это, вероятно, доставка рекламы. «Пожалуйста, выберите случайное объявление с заданной вероятностью» ... однако оно мне нужно для другой цели, а просто для того, чтобы дать вам последнюю картину того, что оно должно делать.
редактирование:
Благодаря ответу Kens я подумал о следующем подходе:
вычислить случайное значение из 0-суммы (отчетливое повышение)
SET @randval = (выбрать ceil (rand () * sum (DISTINCT boost)) из теста);
выбор коэффициента усиления из всех различных коэффициентов усиления, которые суммируются, превышает случайное значение
тогда мы имеем в нашем 1-м примере 1 с 0,1, 2 с 0,2 и 7 с вероятностью 0,7.
- теперь выберите одну случайную запись из всех записей, имеющих этот коэффициент усиления
ПРОБЛЕМА: , потому что количество записей с одним повышением всегда различно. Например, если есть только 1 усиленная запись, я получаю ее в 1 из 10 вызовов, но если есть 1 миллион с 7, каждый из них почти никогда не возвращается ...
так что это не сработает :( пытаюсь уточнить это.
Мне нужно как-то включить количество записей с этим коэффициентом повышения ... но я как-то застрял на этом ...