Mysql RAND()函数基于其他一些值

时间:2017-01-28 22:54:34

标签: mysql sql mariadb

我有这个表结构:

  id | product | value
-----+---------+--------
  1  |  test1  |  10
-----+---------+--------
  2  |  test2  |  30
-----+---------+--------
  3  |  test3  |  25
-----+---------+--------
  4  |  test4  |  20
-----+---------+--------
  5  |  test5  |  15
-----+---------+--------
  6  |  test6  |  35
-----+---------+--------

这是我想向我的用户推荐的一些产品,我有兴趣在我的主页上展示4种产品(并非所有产品),最有价值的产品一个例外。< / p>

所以通常我想要显示这些产品的所有时间:test6, test2, test3, test4。唯一的问题是我不时想要显示一些其他产品,但速度较低。所以,如果我不想要这个,我可能会order by value desc。但问题是我不希望我的用户一直看到相同的4种产品而感到无聊,我希望不时在我的列表中插入一两个其他产品。

现在我知道mysql有一个RAND()函数,但我不知道如何使用它来进行查询以完全按照我想要的那样。

通过匹配,它应该像这样工作:

我们将所有值添加到10+30+25+20+15+35 = 135,我们应用三分法来查看每种产品的随机费率。

135 = 100%
------------
10  = 7.4%
30  = 22.2%
25  = 18.5%
20  = 14.8%
15  = 11.1%
35  = 25.9%

因此,考虑到这个百分比,我想提出一个查询,它将返回使用随机的4个产品的列表,但也会根据这些百分比考虑哪个产品有更多的机会。

不要问我尝试了什么,因为我不是mysql专家,我知道如何在PHP中执行此操作但我想知道这是否甚至可以仅使用mysql,以及我如何做到这一点

1 个答案:

答案 0 :(得分:1)

您可以使用变量执行此操作。获取累计总和,对其进行标准化,然后使用rand()

select t.*
from (select t.*, (@v := @v + value) as running_value
      from t cross join
           (select @v := 0) params
     ) t cross join
     (select sum(value) as sum_value
      from t
     ) total
order by (rand() between (t.running_value - t.value)/total.sum_value and t.running_value / total.sum_value) desc,
         rand();

以上可以简化。此外,rand()中的order by可能会重复计算很多次。我认为这更好:

select t.*
from (select t.*, (@v := @v + value) as running_value, rand() as rnd
      from t cross join
           (select @v := 0) params
     ) t 
order by (rnd between (t.running_value - t.value)/@v and t.running_value/@v) desc;

编辑:

现在我正在考虑它,order by中的二进制结果是非常正确的。这适用于选择一行,但不一定是为了排序。

我认为这是一种更好的方法:

select t.*
from (select t.*, rand() as rnd
      from t 
     ) t 
order by rnd * t.value desc;