我有这个表结构:
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,以及我如何做到这一点
答案 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;