以概率选择RAND()

时间:2018-11-23 14:37:30

标签: php select mysqli phpmyadmin

我想显示“问题”表的10行,其中type_id = 1的问题概率为0.2,type_id = 2的问题概率为0.8。 在我的要求下,如何增加概率?

$query = "select * from questions ORDER BY RAND() LIMIT 10";

enter image description here

我想显示10个问题,其中20%的问题是type_id = 2,而80%的问题是type_id = 1。

有人可以帮我吗?

1 个答案:

答案 0 :(得分:1)

正如我在评论中指出的那样,如果要包含概率或类似的东西,将无法使用像ORDER BY RAND()这样明显的东西。 ORDER BY RAND()根本不支持这种事情。 ORDER BY RAND()的运行速度也很慢,而且无论如何都不能真正用于任何大小的数据库。

您可以使用很多方法来对加权或概率进行随机排序;我不会尝试全部讨论;我只会给您一个相对简单的方法,但是请注意,最适合您的技术取决于您的特定用例。

一种简单的方法如下:

  1. 在表上创建一个名为weight或类似名称的新整数字段。
  2. 为此字段添加数据库索引,以使您能够快速查询它。
  3. 将第一条记录的值设置为等于其权重的整数。即0.2的概率可能是20的权重。
  4. 将每个后续记录设置为此字段的最大值加上该记录的权重。因此,如果第二条记录也是0.2,它将得到40的值;如果之后的值只有0.1,则为50;等等。
  5. 对添加的任何新记录也同样如此。

现在您可以选择随机记录,每个记录的权重如下:

SELECT * FROM questions 
WHERE weight >= FLOOR(RAND() * (SELECT MAX(weight) FROM questions))
ORDER BY weight
LIMIT 1

(请注意,我正在写这篇文章,很急,没有资源可以对其进行测试;我没有运行此查询,所以我可能语法错误,但是基本技巧是合理的)

这将选择一个介于零和最大weight值之间的随机数,然后查找具有最接近该随机数weight的问题记录。

此外,由于为weight字段建立了索引,因此该查询将快速高效。

此技术的缺点:假定任何给定记录的权重都不会改变。如果确实需要更改记录的权重,则必须在索引中的每个记录之后更新权重值。

[编辑]

让我们想象一个像这样的表:

id   Name
 1   Question One
 2   Question Two
 3   Question Three
 4   Question Four
 5   Question Five

在此示例中,我们希望问题1和2的概率为0.2,问题3的概率为0.1,问题4和5的概率为0.3。这些概率可以通过将它们乘以100来表示为整数。(乘以10也可以,但是100意味着我们也可以拥有0.15之类的概率)

我们添加weight列和它的索引,并如下设置weight值:

id   Name            Weight
 1   Question One      20
 2   Question Two      40         (ie previous value + 20)
 3   Question Three    50         (ie previous value + 10)
 4   Question Four     80         (ie previous value + 30)
 5   Question Five    110         (ie previous value + 30)

现在我们可以运行查询了。

查询FLOOR(RAND() * (SELECT MAX(weight) FROM questions))的随机部分将选择一个介于0到110之间的值。我们假设它给出了68

现在我们其余的查询说要选择weight大于68的第一条记录。在这种情况下,这意味着我们得到的记录是记录#4。

这给了我们概率,因为随机数可以是任意值,但是如果给定记录的权重与前一个权重之间的差距较大,则更有可能选择给定记录。获得记录4的频率是记录3的三倍。