我有一个MySQL表,其中有一行叫做cur_odds,它是一个百分数,表示该行被选中的概率。我该如何查询以实际频率选择行,例如运行100个查询时?我尝试了以下方法,但概率为0.35的行最终被选择的次数约为60-70%。
SELECT * FROM table ORDER BY RAND()*cur_odds DESC
表格中所有cur_odds的值加起来恰好为1。
SELECT * FROM table ORDER BY RAND()*cur_odds DESC
表格中所有cur_odds的值加起来恰好为1。
cur_odds
中的任何数字都不是每行被选中的概率,而只是一个任意权重(相对于所有其他行的“权重”),最好解释为相对于排序表顶部的浮动趋势。每行的实际值是无意义的(例如,您可以有4行的值为0.35、0.5、0.75和0.99,或者您可以有值为35、50、75和99的行,结果将是相同的)。
更新:以下是查询的情况。您有一行的cur_odds
值为0.35。为了说明,我假设其他9行都具有相同的值(0.072)。同样为了说明,假设RAND()返回从0.0到1.0的值(实际上可能是这样)。cur_odds
值乘以从0.0到1.0的RAND()值,为每行分配一个排序值。这意味着具有0.35的行将具有介于0.0和0.35之间的排序值。cur_odds
值为0.35的行比您预期的更经常地出现在第一位。cur_odds
值描述为相对变化权重。它实际上作为最大相对权重,这将涉及一些复杂的数学来确定实际的相关概率。cur_odds
很少更改,您可以实现以下算法:prob_sum
,其内容为:
2)生成一个介于0和1之间的随机数:prob_sum[0] := cur_odds[0]
for 1 <= i <= row_count - 1:
prob_sum[i] := prob_sum[i - 1] + cur_odds[i]
3)找到第一行满足rnd := rand(0,1)
prob_sum > rnd
的条件(如果在prob_sum
上创建了BTREE索引,则查询速度应该会更快):
CREATE INDEX prob_sum_ind ON <table> (prob_sum);
SET @rnd := RAND();
SELECT MIN(prob_sum) FROM <table> WHERE prob_sum > @rnd;