Генерация случайного победителя и отображение шансов на выигрыш - правильно ли я это делаю? - PullRequest
1 голос
/ 01 ноября 2009

Я участвую в конкурсе на веб-сайте, и у меня 3215 участников, которые имеют право на 5x Sony PSP.

Я считаю, что формула для подсчета шансов - totalEntrants - призы / призы:

(3215-5)/5 = 642 так что шансы на выигрыш 642 к 1 - это правда? (Я сосу математику)

А в моей таблице, которая содержит 3215 строк в базе данных, я бы просто выбрал случайную строку, например, так?

SELECT * from entries
WHERE entries.won = 0
ORDER BY RAND()
LIMIT 1

Теперь у меня есть одна строка, и мне нужно установить для столбца won значение 1, чтобы участник не смог снова выиграть, а затем запустить его снова? Я делаю это впервые, поэтому мне просто нужно подтверждение, правильно ли я это делаю.

Ответы [ 5 ]

6 голосов
/ 01 ноября 2009

Это верно.Пять человек могут выиграть, есть 3215 участников, поэтому шансы на победу составляют 3215 ÷ 5, что составляет 1 к 643 или 642 к 1.1 из каждых 643 побед означает, что на 1 победителя приходится 642 проигравших.Обратите внимание на небольшую разовую разницу между «шансом x в y» и «шансом x в y».

Ваш метод выбора выглядит хорошо.Вы также можете выбрать их все сразу, изменив значение на LIMIT 5.

2 голосов
/ 01 ноября 2009

шансы на выигрыш всего участников / призов

Нет необходимости уменьшать количество призов. Например, если у нас есть 2 участника и один приз, шансы равны 2/1, что означает, что у каждого участника есть один из двух шансов на выигрыш (если мы уменьшим количество призов, то это будет 1/1, что означает один к одному - наверняка выиграть ...)

Запрос кажется правильным:

  • Один и тот же участник не будет выбран дважды (при условии, что у вас есть код, который обновляет поле 'won' )
  • Пользователь будет случайно выбран случайным образом, генерируя различный порядок каждый раз при запросе
2 голосов
/ 01 ноября 2009

Почему бы просто не использовать LIMIT 5 для выбора победителей за один шаг?

1 голос
/ 01 ноября 2009

Использование:

CREATE TEMPORARY TABLE won LIKE ENTRIES;

DECLARE numAwards INT DEFAULT 5;

WHILE numAwards > 0 DO

  INSERT INTO won
    (columns...)
    SELECT e.*
      FROM ENTRIES e
     WHERE e.userid NOT IN (SELECT w.userid FROM won)
  ORDER BY RAND()
     LIMIT 1;

  SET numAwards = numAwards - 1;

END WHILE;

Вы также можете использовать:

   SELECT e.*
     FROM ENTRIES e
LEFT JOIN won w ON w.userid = e.userid
    WHERE w.userid IS NULL
  ORDER BY RAND()
     LIMIT 1;

... но нет никакой разницы в производительности - см .: NOT IN против NOT EXISTS против LEFT JOIN / IS NULL: MySQL

ОБНОВЛЕНИЕ : Использование LIMIT 5 не является идеальным, поскольку не гарантирует, что человек выиграет только один раз, если только вы не предполагаете, что человек вошел только один раз (маловероятно).

1 голос
/ 01 ноября 2009

Я думаю, вы не можете выбрать и обновить в одном запросе. Что бы я сделал, это использовал ваш запрос, чтобы выбрать случайного победителя и выполнить обновление в регистре, идентификатор которого был возвращен, чтобы изменить поле «выиграл», чтобы иметь значение 1. Затем вы просто повторите процедуру 4 раза. :)

...