【问题标题】:selecting weighted random distribution from a mysql table从 mysql 表中选择加权随机分布
【发布时间】:2016-11-08 00:53:00
【问题描述】:

我正在尝试编写一个查询,该查询将从表中随机选择一些文章,但这些文章具有被选择的加权机会。我想出了一个解决方案,但对我来说似乎很笨拙,我想知道是否有人对如何做得更好有任何想法。我需要至少 1 篇文章,但如果查询一次返回多篇文章会很有帮助。

这是我的方法:

桌子 --

mysql> describe randomiser;
+---------+----------------------+------+-----+---------+----------------+
| Field   | Type                 | Null | Key | Default | Extra          |
+---------+----------------------+------+-----+---------+----------------+
| id      | int(10) unsigned     | NO   | PRI | NULL    | auto_increment |
| article | varchar(30)          | YES  |     | NULL    |                |
| chance  | smallint(5) unsigned | NO   | MUL | 1       |                |
| low     | int(10) unsigned     | NO   | MUL | 0       |                |
| high    | int(10) unsigned     | NO   |     | 0       |                |
+---------+----------------------+------+-----+---------+----------------+

我的测试人群--

mysql> select * from randomiser;
+----+-------------+--------+-----+------+
| id | article     | chance | low | high |
+----+-------------+--------+-----+------+
|  1 | common      |    128 |   1 |  128 |
|  2 | uncommon    |     64 | 129 |  192 |
|  3 | infrequent1 |     32 | 193 |  224 |
|  4 | infrequent2 |     32 | 225 |  256 |
|  5 | infrequent3 |     32 | 257 |  288 |
+----+-------------+--------+-----+------+

每当有人向表中添加新文章时,都会在插入时更新低值和高值。

我的选择方法--

SET @t:=(SELECT FLOOR( SUM(chance) * RAND() + 1) FROM randomiser);
SELECT article FROM randomiser WHERE @t >= low AND @t <= high;
  1. 是否可以将选择组合成一个有效的语句?
  2. 是否可以编写一个选择来提取多个随机值而不是一个?

注意 - 我根本没有像我定义的那样依附于表格;如果有不同类型的布局,那么它会更有效,我想知道!

【问题讨论】:

    标签: mysql random selection weighted


    【解决方案1】:

    您可以使用以下查询

    select t.article from
    (SELECT article,
    case when FLOOR( SUM(chance) * RAND() + 1) between low and high
             then 1 else 0 end as chance
    FROM randomiser 
    group by article) t
    where t.chance = 1
    

    上面的会使用多个随机值

    【讨论】:

    • 这似乎不起作用。我收到以下错误:ERROR 1111 (HY000): Invalid use of group function
    • @davidfurst 我已更改查询
    • @davidfurst 立即查看
    • 它不再给出错误,而是选择所有值,排序。
    • @davidfurst 立即查看
    【解决方案2】:

    对于一个查询,您可以这样做:

    SELECT article
    FROM randomiser
    WHERE (SELECT FLOOR( SUM(chance) * RAND() + 1) FROM randomiser) BETWEEN low AND high;
    

    SQLFiddle Demo

    或者使用INNER JOIN:

    SELECT article, `range`
    FROM randomiser
    INNER JOIN (
        SELECT
            FLOOR( SUM(chance) * RAND() + 1) AS `range`
        FROM randomiser
    ) t
    WHERE `range` >= low AND `range` <= high;
    

    SQLFiddle Demo

    【讨论】:

    • 第一个似乎不起作用。它将选择空集以及两个相邻的值。第二个似乎工作得很好。 :) 谢谢 !我想使用它来获取任意数量的随机文章的唯一方法是在控制程序的循环中多次调用它,对吧?或者你有什么办法可以得到几个随机值?
    • 我想它可以使用多个随机“范围”值来完成,并使用AS 分配不同输出的名称,以便在获取后区分它们,但这似乎也很笨拙。我得再考虑一下。
    • 通过使用第二种方法的变体(使用内连接)和union,我能够找到返回多个随机文章的问题的解决方案。它可能不是最好的,但似乎表现不错。谢谢你的帮助!
    • @davidfurst 太好了,很高兴能帮到你。
    猜你喜欢
    • 1970-01-01
    • 2015-07-05
    • 2010-09-08
    • 2011-05-26
    • 1970-01-01
    • 2017-12-26
    相关资源
    最近更新 更多