我有一个MySQL表,其中有一个名为cur_odds的行,它是一个百分数,表示该行被选中的概率。例如,当您运行100个查询时,我如何创建一个查询,使其以大约相同的频率选择行?
我尝试了以下方法,但概率为0.35的行最终被选中的概率约为60-70%。
SELECT * FROM table ORDER BY RAND()*cur_odds DESC表中cur_odds的所有值恰好相加为1。
发布于 2010-04-27 04:47:37
如果cur_odds很少更改,您可以实现以下算法:
1)新建一个列prob_sum,该列
prob_sum := cur_odds
对于1 <= I <= row_count - 1:
prob_sumi := prob_sumi -1+ cur_oddsi
2)生成一个从0到1的随机数:
rnd := rand(0,1)
3)找到prob_sum > rnd的第一行(如果在prob_sum上创建BTREE索引,查询速度会快得多):
CREATE INDEX prob_sum_ind ON (prob_sum);
设置@rnd := RAND();
SELECT MIN( prob_sum ) FROM WHERE prob_sum> @rnd;
发布于 2010-04-27 03:23:03
对于上面的SQL语句,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的值(实际上可能是)。
每次运行此SELECT语句时,通过将行的RAND值乘以cur_odds ()值(从0.0到1.0 ),为每行分配一个排序值。这意味着具有0.35的行将具有介于0.0和0.35之间的排序值。
每隔一行(值为0.072)将有介于0.0和0.072之间的排序值。这意味着您的一行的排序值大于0.072的可能性约为80%,这意味着没有任何其他行的排序值可能更高。这就是为什么cur_odds值为0.35的行排在第一位的次数比您预期的要多。
我错误地将cur_odds值描述为相对更改权重。它实际上起到了最大相对权重的作用,然后需要一些复杂的数学运算来确定涉及的实际相对概率。
我不确定您需要的东西是否可以用直接的T-SQL来完成。我已经实现了很多次加权概率选择器(具有讽刺意味的是,我今天早上甚至要问一个关于最佳方法的问题),但总是在代码中实现。
https://stackoverflow.com/questions/2716163
复制相似问题