выберите RAND () с вероятностью - PullRequest
0 голосов
/ 23 ноября 2018

Я хочу отобразить 10 строк таблицы «вопросов» с вероятностью 0,2 вопроса, которые имеют type_id = 1, и вероятностью 0,8 вопроса, которые имеют type_id = 2.Ниже моего запроса, как добавить вероятность?

$query = "select * from questions ORDER BY RAND() LIMIT 10";

enter image description here

Я хочу отобразить 10 вопросов, 20% которых имеют type_id = 2и 80% имеют type_id = 1.

Может кто-нибудь помочь мне, пожалуйста?

1 Ответ

0 голосов
/ 26 ноября 2018

Как я отмечал в комментариях, вы не сможете использовать что-либо столь же очевидное, как ORDER BY RAND(), если хотите включить вероятности или что-то подобное.ORDER BY RAND() просто не поддерживает подобные вещи.ORDER BY RAND() также очень медленный и не очень подходит для использования в базе данных любого значительного размера в любом случае.

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

Простой подход будет выглядеть примерно так:

  1. Создайте в вашей таблице новое целочисленное поле с именем weight или чем-то похожим.
  2. Добавьте индекс БД для этого поля, чтобы вы могли быстро запросить его.
  3. Установите первую записьк значению, равному его весу как целому числу.т. е. вероятность 0,2 может быть весом 20.
  4. Установите для каждой последующей записи максимальное значение этого поля плюс вес для этой записи.Таким образом, если вторая запись также равна 0,2, она получит значение 40;если после этого только 0,1, это будет 50;и т. д.
  5. Аналогичным образом действуйте для любых новых записей, которые добавляются.

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

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...