我需要SQL查询来确定随机获胜者。每个用户都拥有自己的胜算。 wins_odds值越高,用户获胜的机会就越多。以下是表结构:
id email winning_odds
1 test@test.com 3
2 test2@test.com 5
3 test3@test.com 2
4 test4@test.com 1
5 test5@test.com 9
MySQL数据库。表有大约100000行。只有一个赢家,一次。电子邮件是独一无二的。有人有解决方案吗?
感谢。
答案 0 :(得分:1)
Select email from user order by winning_odds*rand() limit 1
答案 1 :(得分:1)
我真的很喜欢这个问题,我发布了postgresql的答案。
select
*, generate_series(1, mytable.winning_odds)
from
mytable
order by
random()
limit 1;
这是它的工作原理。对于表格的每一行,我们将该行复制N次作为您的获胜赔率。
因此,您首先获得并且不限制查询结果:
5 | test5@test.com | 9 | 9
2 | test2@test.com | 5 | 3
3 | test3@test.com | 2 | 1
1 | test@test.com | 3 | 1
5 | test5@test.com | 9 | 5
1 | test@test.com | 3 | 3
5 | test5@test.com | 9 | 2
2 | test2@test.com | 5 | 4
2 | test2@test.com | 5 | 5
5 | test5@test.com | 9 | 1
4 | test4@test.com | 1 | 1
5 | test5@test.com | 9 | 7
5 | test5@test.com | 9 | 4
5 | test5@test.com | 9 | 6
2 | test2@test.com | 5 | 1
5 | test5@test.com | 9 | 8
3 | test3@test.com | 2 | 2
1 | test@test.com | 3 | 2
2 | test2@test.com | 5 | 2
5 | test5@test.com | 9 | 3
现在,随机选择生成的表格中的任何一行都会反映出wins_odds字段的概率。
您所要做的就是随机订购并获得第一张唱片。
9 | test5@test.com | 9 | 2
此致
答案 2 :(得分:1)
我猜测“赔率”不是整数,你想要一个“9”的东西比“1”的可能性高九倍。
执行此操作的正确方法是累计金额。然后在累积和的最小值和最大值之间生成随机值,并选择该范围内的记录。以下查询在MySQL中执行此操作:
select t.*
from (select t.*,
coalesce((select sum(odds) from t t2 where t2.id < t.id), 0) as cumsum,
const.sumodds
from t cross join
(select rand()*sum(odds) as val from t) const
) t
where val between cumsum and cumsum + t.odds
然而,这是在进行非等值连接,并且在MySQL中可能会非常昂贵。其他数据库能够在单个查询中执行累积求和。 MySQL没有一种有效的方法。
如何优化查询取决于问题中的某些其他因素。 “赔率”有多少不同的值?你能用临时表吗?
我现在没有时间写出解决方案,但有一种更有效的方法。 Y的想法是将问题分成两个搜索。第一个将找到哪个“赔率”值获胜。第二个将找到哪一行获胜。
以下是详细信息:
(1)按赔率将数据汇总到表格中。该表有11行,并包含每个的“赔率”和“计数”。
(2)计算每一行的“count * odds”之和,从第一行的0开始。您可以使用上述查询作为指导,因为这是一个很小的数据,它将快速运行。
(3)将随机数计算为rand()*<sum of all odds>
。现在,找出数字在cumsum和cumsum +赔率之间的几率。
(4)现在返回原始表并发出如下查询:
select *
from t
where odds = <winning odds>
order by rand()
limit 1
答案 3 :(得分:0)
如果我正确理解了这个问题,你就会问如何从表中选择一个随机记录。这应该有效:
SELECT *
FROM tableName
ORDER BY RAND() LIMIT 0,1;
现在还清楚你打算如何使用winner_odds值。