Как я отмечал в комментариях, вы не сможете использовать что-либо столь же очевидное, как ORDER BY RAND()
, если хотите включить вероятности или что-то подобное.ORDER BY RAND()
просто не поддерживает подобные вещи.ORDER BY RAND()
также очень медленный и не очень подходит для использования в базе данных любого значительного размера в любом случае.
Существует целый ряд подходов, которые вы можете использовать для выполнения случайного порядка сортировки с весами или вероятностями;Я не собираюсь обсуждать их все;Я просто дам вам относительно простой, но, пожалуйста, помните, что лучший метод для вас будет зависеть от вашего конкретного случая использования.
Простой подход будет выглядеть примерно так:
- Создайте в вашей таблице новое целочисленное поле с именем
weight
или чем-то похожим. - Добавьте индекс БД для этого поля, чтобы вы могли быстро запросить его.
- Установите первую записьк значению, равному его весу как целому числу.т. е. вероятность 0,2 может быть весом 20.
- Установите для каждой последующей записи максимальное значение этого поля плюс вес для этой записи.Таким образом, если вторая запись также равна 0,2, она получит значение 40;если после этого только 0,1, это будет 50;и т. д.
- Аналогичным образом действуйте для любых новых записей, которые добавляются.
Теперь вы можете выбрать случайную запись с разными весами для каждой записи следующим образом:
SELECT * FROM questions
WHERE weight >= FLOOR(RAND() * (SELECT MAX(weight) FROM questions))
ORDER BY weight
LIMIT 1
(обратите внимание, я пишу ответ в спешке и без ресурсов для его проверки; я не выполнил этот запрос, поэтому, возможно, у меня неправильный синтаксис, но основнойтехника звучит)
Это выберет случайное число между нулем и наибольшим значением weight
, а затем найдет запись вопроса, которая имеет значение, наиболее близкое к этому случайному числу weight
..
Кроме того, поскольку поле weight
проиндексировано, этот запрос будет быстрым и эффективным.
Недостатки этого метода: предполагается, что веса для любой данной записи не изменятся,Если вес записи действительно нужно изменить, то вам придется обновлять значение веса для каждой записи после нее в индексе.
[EDIT]
Давайте представим таблицу, подобную этой:
id Name
1 Question One
2 Question Two
3 Question Three
4 Question Four
5 Question Five
В этом примере мы хотим, чтобы вопросы 1 и 2 имели вероятность 0,2, вопрос 3 - 0,1, а вопросы 4 и 5 - 0,3.Эти вероятности могут быть выражены в виде целых чисел путем умножения их на 100. (умножение на 10 также работает, но 100 означает, что у нас могут быть вероятности, например, 0,15)
Мы добавляем столбец weight
и индекс для негои установите значения weight
следующим образом:
id Name Weight
1 Question One 20
2 Question Two 40 (ie previous value + 20)
3 Question Three 50 (ie previous value + 10)
4 Question Four 80 (ie previous value + 30)
5 Question Five 110 (ie previous value + 30)
Теперь мы можем выполнить наш запрос.
Случайная часть запроса FLOOR(RAND() * (SELECT MAX(weight) FROM questions))
выберет значение от нуля до 110Давайте представим, что это дает 68
.
Теперь остальная часть нашего запроса говорит выбрать первую запись, где weight
больше 68. В этом случае это означает, что полученная нами запись является записью# 4.
Это дает нам нашу вероятность, потому что случайное число может быть любым, но с большей вероятностью выберет данную запись, если разрыв между ее весом и предыдущим будет больше.Вы получите запись № 4 в три раза чаще, чем запись № 3.