SQL Выберите случайную строку на основе процента

0

В принципе, мне нужен рандомизатор, но вместо того, чтобы обрабатывать все строки одинаково (по 25% каждый), он должен обрабатывать его на основе процента, назначенного ему.

Например:

Event Chance_Percentage
A          25.00
B          10.00
C          15.00
D          50.00

Как я могу это достичь?

Я использую MySQL.

  • 0
    Какую СУБД вы используете? Синтаксис для генераторов случайных чисел будет отличаться.
  • 0
    @ Error_2646 Я использую MySql
Показать ещё 3 комментария
Теги:

5 ответов

0

Более общее решение:

select e.*, t2.*
  from (
    select event,
      (select coalesce(sum(chance_percentage), 0) 
         from table1 t2 where t2.event < t1.event) as lower_bound,
      (select sum(chance_percentage) 
         from table1 t3 where t3.event <= t1.event) as upper_bound
      from table1 t1) e
  join (select 100.0 * rand() as p) t2
    where t2.p >= e.lower_bound and t2.p < e.upper_bound;
0

Если вы просто хотите выбрать одно поле с вероятностью, равной проценту

Я думаю, что что-то вроде этого отлично работает: Set @mybound: = RAND() * 100; SELECT * FROM Event Где Chance_Percentage <@mybound ORDER BY Chance_Percentage desc limit 1

  • 0
    rand() будет пересчитан для каждой строки. Вполне возможно, что это ничего не вернет.
0

Это довольно легко вычислить на языке программирования приложений, таком как Java, Python, C, php, JavaScript или что еще вы используете. Вы можете просто выбрать все свои строки в своем приложении и выполнить расчет там, где их легко написать.

Если в базе данных нет приложения NEED, то не делайте этого. Используйте правильный инструмент для правильной работы. База данных в первую очередь предназначена для сохранения, а не для вычислений.

См. Также проблему XY.

  • 0
    Ты прав, я просто усложняю себе.
  • 0
    @confusedOne. , , Не за что. Это довольно легко вычислить в SQL.
0

Сделайте кумулятивную сумму, а затем запустите rand() один раз:

select t.event
from (select t.*, (@cume_p = @cume_p + p) as cume_p
      from t cross join
           (select @cume_p := 0, @rand = rand()) params
     ) t
where @rand >= cume_p - p and
      @rand < cume_p;

Обратите внимание, что rand() вызывается ровно один раз. Значение сохраняется в переменной; это произвольный выбор. Он также может быть в подзапросе:

select t.event
from (select t.*, (@cume_p = @cume_p + p) as cume_p
      from t cross join
           (select @cume_p := 0) params
     ) t cross join
     (select rand() as r) r
where r.r >= cume_p - p and
      r.r < cume_p;
0

У меня нет MySQL на моей машине, поэтому это не проверено, но я думаю, что эта общая идея будет работать.

    SELECT Event
      FROM Your_Table
     WHERE CASE WHEN Event = 'A' THEN 
                CASE WHEN RAND() <= .25 THEN 1
                     END
                WHEN Event = 'B' THEN 
                CASE WHEN RAND() <= .1 THEN 1
                     END
                WHEN Event = 'C' THEN 
                CASE WHEN RAND() <= .15 THEN 1
                     END
                WHEN Event = 'D' THEN 
                CASE WHEN RAND() <= .5 THEN 1
                     END
            END = 1;
  • 0
    Таблица, которую я предоставил, была только примером, в моей реальной таблице у меня более 1400 строк, и проценты рассчитываются на основе суммы / общей суммы, никакие 2 процента не будут одинаковыми. Поэтому я не думаю, что ручное определение CASE - это правильный путь, поскольку они составляют 1400 уникальных процентов: /
  • 0
    @confusedOne Меня не беспокоит производительность с 1400 строками. Я не буду беспокоиться о производительности операторов CASE в целом, если они не находятся в условиях соединения.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню