2010-04-26 3 views
6

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

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

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

Все значения cur_odds в таблице составляют до 1 точно.

+0

ORDER BY RAND() может быть очень медленным с большими наборами данных, так как это O (n log (n)). Сколько строк будет у вашей таблицы? –

ответ

4

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

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

prob_sum [0]: = cur_odds [0]

для 1 = < < я = row_count - 1:

prob_sum [I]: = prob_sum [я - 1] + cur_odds [I]

2) Генерировать случайное число от 0 до 1:

RND: = Rand (0,1)

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

CREATE INDEX prob_sum_ind ON < таблицы> (prob_sum);

SET @rnd: = RAND();

SELECT MIN (prob_sum) FROM < таблица> WHERE prob_sum> @rnd;

+0

Лучший ответ здесь: http://stackoverflow.com/a/12301949/901739 –

3

Учитывая ваше выше заявление 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. Это означает, что вероятность того, что ваша одна строка будет иметь значение сортировки, превышающее 0.072, будет примерно на 80%, что означает, что существует отсутствие возможной вероятности, что любая другая строка может быть отсортирована выше. Вот почему ваша строка с cur_odds значением 0,35 приближается первым чаще, чем вы ожидаете.

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

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

+0

На самом деле, у меня есть 10 строк, а 10 значений в cur_odds равны 1 точно. –

+1

Попробуйте умножить все значения на 10 (так, чтобы они составляли точно 10.0), и вы увидите, что получаете одинаковые результаты заказа. Или вы можете разделить их на 3 или умножить на 100 и т.д. – MusiGenesis

Смежные вопросы