我有一张抽奖的获奖者名单,其中每位获奖者在一年中获得了多个积分。有1300名注册用户,积分在50到43,000之间。我需要能够选择一个随机的赢家,这是直截了当的,但我所面临的挑战是建立逻辑,其中每个点都算作抽奖的入场券。非常感谢任何帮助。
约翰
答案 0 :(得分:0)
您的脚本看起来与此类似:
脚本1:
DECLARE @Name varchar(100),
@Points int,
@i int
DECLARE Cursor1 CURSOR FOR SELECT Name, Points FROM Table1
OPEN Cursor1
FETCH NEXT FROM Cursor1
INTO @Name, @Points
WHILE @@FETCH_STATUS = 0
BEGIN
SET @i = 0
WHILE @i < @Points
BEGIN
INSERT INTO Table2 (Name)
VALUES (@Name)
SET @i = @i + 1
END
FETCH NEXT FROM Cursor1 INTO @Name, @Points
END
DEALLOCATE Cursor1
我创建了一个只有Name和Points列(varchar(100)和int)的表(Table1),我创建了一个游标,以便查看Table1中的所有记录,然后循环遍历Points然后将每条记录插入另一张表(表2)。
然后根据Points列导入Name。
脚本2:
DECLARE @Name varchar(100),
@Points int,
@i int,
@Count int
CREATE TABLE #temptable(
UserEmailID nvarchar(200),
Points int)
DECLARE Cursor1 CURSOR FOR SELECT UserEmailID, Points FROM Table1_TEST
OPEN Cursor1
FETCH NEXT FROM Cursor1
INTO @Name, @Points
WHILE @@FETCH_STATUS = 0
BEGIN
SET @i = 0
WHILE @i < @Points
BEGIN
INSERT INTO #temptable (UserEmailID, Points)
VALUES (@Name, @Points)
SET @i = @i + 1
END
FETCH NEXT FROM Cursor1 INTO @Name, @Points
END
DEALLOCATE Cursor1
SELECT * FROM #temptable
DROP TABLE #temptable
在Script2中,我已根据请求将结果导入TEMP表。 该脚本现在遍历Table1中的每条记录,并根据表1中的点数将个人UserEmailID和Points导入TEMP表。
因此,如果John总共得到3分,而Sarah 2,脚本会将Johns UserEmailID导入TEMP表3次,将Sarah导入2次。
如果在TEMP表上应用随机选择器,它将随机选择一个人。 John显然有更好的获胜机会,因为他在TEMP表中有3条记录,而Sarah只有2条记录。
假设Johns UserEmailID为1而Sarah为2: 然后,TEMP表的OUTPUT为:
UserEmailID | Points
1 | 3
1 | 3
1 | 3
2 | 2
2 | 2
如果您需要清楚,请告诉我。 希望这会有所帮助。
答案 1 :(得分:0)
您可以使用以下方法进行加权抽奖:
以下是此方法的标准SQL:
with u as (
select u.*,
coalesce(lead(rangestart) over (order by points) as rangeend, 1)
from (select u.*,
sum(points*1.0) over (order by points) / sum(points) over () as rangestart
from users u
) u
),
r as (
select random() as rand
)
select u.*
from u
where r.rand between rangestart and rangeend;
除了使用窗口函数(在很多情况下可以由相关子查询处理)之外,确切的格式取决于随机数生成器对查询是否具有确定性(例如random()
返回一个查询的SQL Server值,无论在查询中调用的频率如何)或非确定性(例如在其他数据库中)。此方法只需要一个随机数生成器的值,因此它可以使用任何一种方法。
答案 2 :(得分:0)
所以你想要一个拥有1000分的胜利者,只有500分的可能性增加一倍。
按任何顺序对获胜者进行排序,并为这些点创建一个总计:
id points winner1 100 winner2 50 winner3 150
给出:
id points from to winner1 100 1 100 winner2 50 101 150 winner3 150 151 300
然后与从1到总和(点数)的随机数进行比较,在示例中为1到300之间的数字。找到具有该数字范围的获胜者并完成。
select winpoints.id_winner
from
(
select
id as id_winner,
coalesce(sum(points) over(order by id rows between unbounded preceding and 1 preceding), 0) + 1 as from_points,
sum(points) over(order by id rows between unbounded preceding and current row) as to_points
from winners
) winpoints
where (select floor(rand() * (sum(points) from winners)) + 1)
between winpoints.from_points and winpoints.to_points;
答案 3 :(得分:0)
此解决方案也适用于分数点/权重。它创建了一个帮助表usersum
。
create table user (id int primary key, points float);
insert into user values (1, 0.5), (2, 0), (3, 1);
create table usersum (id int primary key, pointsum float);
insert into usersum
select id, (select sum(points) from user b where b.id <= a.id)
from user a;
set @r = rand() * (select max(pointsum) from usersum);
select @r, usersum.* from usersum where pointsum >= @r order by id limit 1;