Выберите случайную строку из MySQL (с вероятностью) - PullRequest
6 голосов
/ 26 апреля 2010

У меня есть таблица MySQL, в которой есть строка с именем cur_odds, представляющая собой процентное число с процентной вероятностью, что эта строка будет выбрана. Как мне сделать запрос, который фактически выберет строки примерно с такой частотой, когда вы, например, выполните 100 запросов?

Я попробовал следующее, но строка с вероятностью 0,35 заканчивается тем, что ее выбирают в 60-70% случаев.

SELECT * FROM table ORDER BY RAND()*cur_odds DESC

Все значения cur_odds в таблице в сумме равны 1.

Ответы [ 2 ]

4 голосов
/ 27 апреля 2010

Если cur_odds изменяется редко, вы можете реализовать следующий алгоритм:

1) Создайте еще один столбец prob_sum, для которого

prob_sum [0]: = cur_odds [0]

для 1 <= i <= row_count - 1: </p>

prob_sum [i]: = prob_sum [i - 1] + cur_odds [i]

2) Генерация случайного числа от 0 до 1:

rnd: = rand (0,1)

3) Найдите первую строку, для которой prob_sum > rnd (если вы создаете индекс BTREE для prob_sum, запрос должен работать намного быстрее):

CREATE INDEX prob_sum_ind ON

3 голосов
/ 26 апреля 2010

Учитывая вышеприведенный оператор SQL, все числа, которые у вас есть в cur_odds, равны , а не вероятности, что каждая строка выбрана, а вместо этого - просто произвольный вес (относительно "весов" всех другие строки), которые лучше всего интерпретировать как относительную тенденцию плавать в верхней части отсортированной таблицы. Фактическое значение в каждой строке не имеет смысла (например, у вас может быть 4 строки со значениями 0,35, 0,5, 0,75 и 0,99, или вы можете иметь значения 35, 50, 75 и 99, и результаты будут одинаковыми).

Обновление: Вот что происходит с вашим запросом. У вас есть одна строка со значением cur_odds 0,35. Для иллюстрации я собираюсь предположить, что все остальные 9 строк имеют одинаковое значение (0,072). Также для иллюстрации, давайте предположим, что RAND () возвращает значение от 0,0 до 1,0 (это может на самом деле).

Каждый раз, когда вы запускаете этот оператор SELECT, каждой строке присваивается значение сортировки путем умножения ее значения cur_odds на значение RAND () от 0,0 до 1,0. Это означает, что строка с 0,35 будет иметь значение сортировки от 0,0 до 0,35.

Каждая вторая строка (со значением 0,072) будет иметь значения сортировки в диапазоне от 0,0 до 0,072. Это означает, что существует приблизительно 80% вероятности того, что ваша строка будет иметь значение сортировки больше 0,072, что будет означать, что нет вероятного , что любая другая строка может быть отсортирована выше. Вот почему ваш ряд со значением cur_odds, равным 0,35, появляется первым чаще, чем вы ожидаете.

Я неправильно описал значение cur_odds как относительное изменение веса. На самом деле он функционирует как максимальный относительный вес, который затем потребует сложной математики для определения фактической относительной вероятности.

Я не уверен, что вам нужно сделать с прямым T-SQL. Я реализовал взвешенный сборщик вероятностей много раз (иронично, я даже собирался задать вопрос о лучших методах для этого утра), но всегда в коде.

...