SQL:随机选择一行,但考虑到权重

FWH*_*FWH 10 mysql sql random select

我正在使用MySQL.我有一张看起来像这样的表:

id: primary key
content: varchar
weight: int
Run Code Online (Sandbox Code Playgroud)

我想要做的是从该表中随机选择一行,但考虑到重量.例如,如果我有3行:

id, content, weight
1, "some content", 60
2, "other content", 40
3, "something", 100
Run Code Online (Sandbox Code Playgroud)

第一行有30%被选中的机会,第二行被选中的几率为20%,第三行被选中的几率为50%.

有没有办法做到这一点 ?如果我必须执行2或3个查询,这不是问题.

use*_*413 10

我认为最简单的实际上是使用加权水库采样:

SELECT
  id,
  -LOG(RAND()) / weight AS priority
FROM
  your_table
ORDER BY priority
LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

这是一个很好的方法,它可以让您从 N 个元素中选择 M 个,其中每个元素被选择的概率与其权重成正比。当您碰巧只需要一个元素时,它也能正常工作。本文介绍了该方法。请注意,他们选择了 POW(RAND(), 1/weight) 的最大值,这相当于选择了 -LOG(RAND()) / weight 的最小值。

  • 这是一个很棒的答案!谢谢你!只需添加我的两分钱:编写 log(1-rand()) 来避免 log(0) 不是更优雅吗,因为随机值可能在 [0,1[ (但是未检查)中? (2认同)

Dew*_*wfy -4

我不记得如何在 mysql 中 RND(),但这里有 MSSQL 的工作示例:

SELECT TOP(1) (weight +RAND ()) r, id, content, weight FROM Table
ORDER BY 1 DESC
Run Code Online (Sandbox Code Playgroud)

如果 TOP(1) 不适用,您只需从总结果集中获取第一条记录。

  • `SELECT * FROM table ORDER BY Weight*random() DESC LIMIT 1` 看起来更好、更短并且传输的数据更少;-) (5认同)