Как создать случайный элемент с другой частотой из MySQL - PullRequest
0 голосов
/ 08 июня 2011

У меня есть следующая таблица:

Potion { id, name, freq }

Я раздавал зелья пользователям «случайным образом». но я хочу иметь возможность контролировать частоту случайности, потому что некоторые зелья сильнее других. Какой лучший способ сделать это?

Я думаю о чем-то вроде этого:

  id | name  |   freq
  -------------------
   1 | light |     5
   2 | fire  |    10
   3 | water |    10
   4 | earth |    10
   5 | air   |     5

свет и воздух более мощные, чем огонь, вода и земля, поэтому они имеют меньшие частоты.

sum = select sum(*) from potions;
x = random(1..sum)
table = select * from potions;
offset = 0
for each element in table
  if offset + element[freq] > x
     chosen = element[name]
  end
  offset += element[freq]
end

Я думаю, что приведенный выше код (ruby + sql) будет работать, но он не масштабируется, и я очень сомневаюсь, что это наиболее эффективный способ сделать это. Может ли кто-нибудь помочь мне сделать это?

Заранее спасибо,

Ответы [ 2 ]

0 голосов
/ 08 июня 2011

Сначала необходимо создать представление поверх RAND(), чтобы оно возвращало одно и то же значение для каждого вызова во время выполнения (в противном случае вы получите странные результаты):

create view constant_rand as select rand() as rand;

Далее выберите случайныйстрока, взвешенная по совокупной частоте:

select id
from potion p1
join constant_rand
where rand * (select sum(freq) from potion) between
    -- sum of freq below this row
    ifnull((select sum(freq) from potion p2 where p2.id < p1.id), 0)
    -- sum of freq below and including this row
    and (select sum(freq) from potion p2 where p2.id <= p1.id);
0 голосов
/ 08 июня 2011

Я сомневаюсь, что вам нужно что-то более эффективное.Что вы пытаетесь масштабировать до?Я бы оставил все как есть.Хорошая работа!

Вы можете организовать элементы в древовидную структуру с узлами, хранящими общее количество дочерних элементов.Это спасло бы вас от перебора всего набора.Но для этого все кончено.

...