我的数据库中有一些条目,例如我的视频,其中包含评分,受欢迎程度和其他因素。在所有这些因素中,我计算一个或多个可能性因素,或者说是一个提升因素。
所以本质上我有ID和BOOST字段。boost的计算方式是一个整数,表示该条目在比较中应该被击中的频率的百分比。
ID Boost 1 1 2 2 3 7
因此,如果我无限期地运行随机函数,我应该在ID 1上获得X次点击,在ID 2上获得2倍,在ID 3上获得7倍。
因此,每次点击都应是随机的,但概率为(boost / sum of boosts)。因此,在此示例中ID 3的概率应为0.7(因为总和为10。为简单起见,我选择了这些值)。
(boost / sum of boosts)
我想到了类似以下查询的内容:
SELECT id FROM table WHERE CEIL(RAND() * MAX(boost)) >= boost ORDER BY rand();
不幸的是,在考虑了表中的以下条目后,这行不通了:
ID Boost 1 1 2 2
机会只有50/50的情况下,只有第二个元素或两个元素可供选择。
因此,将0.5命中分配给第二个元素,将0.5命中分配给(第二个和第一个)元素,这些元素是随机选择的,因此每个0.25。所以我们最终得到0.25 / 0.75的比率,但是应该是0.33 / 0.66
我需要一些修改或新的方法来以良好的性能执行此操作。
我也考虑过要累积存储boost字段,所以我只需要从(0-sum())进行范围查询,但是如果我更改了它或开发了一些交换算法或其他东西,那么我将不得不重新索引一个项目之后的所有内容。真的不是优雅的东西。
0-sum()
插入/更新和选择都应该很快!
您对此问题有解决方案吗?
要考虑的最佳用例可能是广告投放。“请以给定的概率选择一个随机广告” …但是我需要将其用于其他目的,而只是给您最后一张图片它应该做什么。
编辑:
感谢kens的回答,我想到了以下方法:
SET @randval =(从测试中选择ceil(rand()* sum(DISTINCT boost)));
那么我们在第一个示例1中的概率为0.1,2的概率为0.2,7的概率为0.7。
问题: 因为一次提升的条目数总是不同的。例如,如果只有1个增强的项,那么我会在10个调用中有1个得到它,但是如果有1个具有7个调用,则几乎不会返回它们……因此这行不通:(尝试对其进行优化。
我必须以某种方式包括具有该提升因子的条目数…但是我却以某种方式停留在那…
您需要为每行生成一个随机数并对其加权。
在这种情况下,RAND(CHECKSUM(NEWID()))绕过的“每个查询”评估RAND。然后只需将其乘以boost,然后将ORDER BY乘以结果DESC。该SUM..OVER给你的总升压
RAND(CHECKSUM(NEWID()))
RAND
SUM..OVER
DECLARE @sample TABLE (id int, boost int) INSERT @sample VALUES (1, 1), (2, 2), (3, 7) SELECT RAND(CHECKSUM(NEWID())) * boost AS weighted, SUM(boost) OVER () AS boostcount, id FROM @sample GROUP BY id, boost ORDER BY weighted DESC
如果您有不同的提升值(我想您已经提到过),我也将考虑使用LOG(以e为底)来平滑分布。
最后,ORDER BY NEWID()是不考虑提升的随机性。播种RAND很有用,但不能单独播种。
该示例放到了SQL Server 2008 BTW上