选择随机项目但是某些项目的选择百分比较高?

时间:2017-05-01 12:03:07

标签: c# sql-server random

我正在使用MVC C#和SQL Sever。

我有大约100件物品,我从中选择了2件随机物品。这是一个新的指导直接排序。

 vm = vm.OrderBy(c => Guid.NewGuid()).Take(2).ToList();

但是现在我希望能够标记一个项目的子集,以便选择更高的百分比(20%),然后在更晚的时候将另一个子集标记为50%。

项目列表是静态的。它总是大约100件。

我只是打算强制它并将所选项目的20%以上添加到列表中,然后他们只进行两次随机选择。

vm1 = vm.OrderBy(c => Guid.NewGuid()).Take(1).Single();
vm2 = vm.OrderBy(c => Guid.NewGuid()).Where(_ => _.Id != firstSelectedID).Take(1).Single();

但是我认为在SQL中可能会有一种更清晰,更高效的方式或者我在C#中缺少的东西

1 个答案:

答案 0 :(得分:0)

有一种纯粹的TSQL方式,你可以在C#中以相同的方式编写它,但我不知道如何通过实体框架来实现它。

declare @table table ( letter nchar(1), weight int)
insert into @table values ('A', 1)
insert into @table values ('B', 2)
insert into @table values ('C', 3)
insert into @table values ('D', 4)
insert into @table values ('E', 5)

declare @total int;
select @total = sum(weight) from @table

declare @selected int;
set @selected = rand() * @total

select @selected

select top 1  * from (
select letter, weight, runningTotal = sum(weight) over (order by letter)
 from @table
) data where runningTotal > @selected order by runningTotal

你会得到'E'5个牌,因为它会返回'A'。这大致基于https://en.wikipedia.org/wiki/Fitness_proportionate_selection您可以使用任何可以为您加权的过程替换权重列。

你可以运行

select letter, weight, runningTotal = sum(weight) over (order by letter)
 from @table

了解数据的加权方式。

以下版本更好,因为它在一次操作中完成所有操作,但我将副本留在上面,因为它更清楚发生了什么。

select top 1  * from (
select letter, weight, runningTotal = sum(weight) over (order by letter)
 from @table
) data where runningTotal > rand() * (select sum(weight) from @table) order by runningTotal