如何根据你拥有的票数随机选择一行

xkftehaa  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(349)

我有张table叫 my_users ```
my_id | name | raffle_tickets
1 | Bob | 3
2 | Sam | 59
3 | Bill | 0
4 | Jane | 10
5 | Mike | 12

如你所见 `Sam` 有 `59` 所以他获胜的机会最大。获胜几率: `Sam` = 
59/74 `Bob` = 
3/74 `Jane` = 
10/74 `Bill` = 
0/74 `Mike` =  `12/74` 附言: `74` 是表中的总票数(只是为了让你知道我不是随机挑选的) `74` )
基于此,我如何随机挑选一个赢家,但确保那些谁有更多的抽奖券有更高的机会被随机挑选?获胜者从总票数中扣除1张

UPDATE my_users
SET raffle_tickets = raffle_tickets - 1
WHERE my_id = --- Then I get stuck here...

服务器版本:5.7.30
ffvjumwh

ffvjumwh1#

对于mysql 8+

WITH 
cte1 AS ( SELECT name, SUM(raffle_tickets) OVER (ORDER BY my_id) cum_sum
          FROM my_users ),
cte2 AS ( SELECT SUM(raffle_tickets) * RAND() random_sum  
          FROM my_users )  
SELECT name
FROM cte1
CROSS JOIN cte2
WHERE cum_sum >= random_sum
ORDER BY cum_sum LIMIT 1;

5年+

SELECT cte1.name
FROM ( SELECT t2.my_id id, t2.name, SUM(t1.raffle_tickets) cum_sum
       FROM my_users t1
       JOIN my_users t2 ON t1.my_id <= t2.my_id
       WHERE t1.raffle_tickets > 0
       GROUP BY t2.my_id, t2.name ) cte1
CROSS JOIN ( SELECT RAND() * SUM(raffle_tickets) random_sum
             FROM my_users ) cte2
WHERE cte1.cum_sum >= cte2.random_sum
ORDER BY cte1.cum_sum LIMIT 1;

小提琴

z0qdvdin

z0qdvdin2#

你想从随机样本中得到一个加权拉力。为此,变量可能是最有效的解决方案:

select u.*
from (select u.*, (@t := @t + raffle_tickets) as running_tickets
      from my_users u cross join
           (select @t := 0, @r := rand()) params
      where raffle_tickets > 0
     ) u 
where @r >= (running_tickets - raffle_tickets) / @t and
      @r < (running_tickets / @t);

它所做的是计算票的运行总数,然后除以票的数量得到一个介于0和1之间的数字。例如,这可能会产生:

my_id   name    raffle_tickets  running_tickets       running_tickets / @t
1       Bob          3                3               0.03571428571428571
2       Sam         59               62               0.7380952380952381
4       Jane        10               72               0.8571428571428571
5       Mike        12               84               1

原始行的顺序无关紧要——这就是为什么子查询中没有顺序。
然后将该比率与 rand() 选择特定行。
注意,在外部查询中, @t 是总票数。
这是一把小提琴。

相关问题