6

我有一个 MySQL 表,其中有一个名为 cur_odds 的行,它是一个百分比数字,表示该行将被选中的百分比概率。例如,当您运行 100 个查询时,如何进行查询以实际选择大约该频率的行?

我尝试了以下方法,但概率为 0.35 的行最终会在 60-70% 的时间内被选中。

SELECT * FROM table ORDER BY RAND()*cur_odds DESC

表中 cur_odds 的所有值加起来正好是 1。

4

2 回答 2

4

鉴于您上面的 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 语句时,通过将其cur_odds值乘以从 0.0 到 1.0 的 RAND() 值,为每一行分配一个排序值。这意味着具有 0.35 的行将具有介于 0.0 和 0.35 之间的排序值。

每隔一行(值为 0.072)将具有介于 0.0 和 0.072 之间的排序值。这意味着您的某一行的排序值大于 0.072 的可能性约为 80%,这意味着任何其他行的排序值不可能更高。这就是为什么您的cur_odds值为 0.35 的行首先出现的频率比您预期的要高。

我错误地将该cur_odds值描述为相对变化权重。它实际上起到最大相对权重的作用,然后将涉及一些复杂的数学来确定所涉及的实际相对概率。

我不确定你需要什么可以用直接的 T-SQL 来完成。我已经多次实现了加权概率选择器(具有讽刺意味的是,今天早上我什至要问一个关于最佳方法的问题)但总是在代码中。

于 2010-04-26T19:23:02.900 回答
4

如果cur_odds很少更改,您可以实现以下算法:

1)创建另一列prob_sum,为其

prob_sum[0] := cur_odds[0]

对于 1 <= i <= row_count - 1:

prob_sum[i] := prob_sum[i - 1] + cur_odds[i]

2)生成一个从0到1的随机数:

rnd := 兰德(0,1)

3)找到第一行prob_sum > rnd(如果您在 上创建 BTREE 索引prob_sum,查询应该更快地工作):

CREATE INDEX prob_sum_ind ON <table> (prob_sum);

设置@rnd:=兰德();

SELECT MIN(prob_sum) FROM <table> WHERE prob_sum > @rnd;

于 2010-04-26T20:47:36.850 回答