在T-SQL中绘制抽奖券获胜者

时间:2011-07-28 08:15:36

标签: sql sql-server tsql sql-server-2008

我有下表:

DECLARE @TicketHolder TABLE
(
    [Name] VARCHAR(100),
    Tickets DECIMAL(18, 8)
);

有一些测试值:

INSERT INTO @TicketHolder ([Name], Tickets)
SELECT 'Bob', 10.37
UNION ALL
SELECT 'Lisa', 1
UNION ALL
SELECT 'Robbie', 150.981
UNION ALL
SELECT 'Cathy', 97.888531;
已购买260.239531张门票。 Bob拥有约58%的门票,Cathy约占38%,依此类推:

SELECT [Name], Tickets / (SELECT SUM(Tickets) AS WinProb
FROM @TicketHolder) WinProb FROM @TicketHolder

现在,我需要根据每个人拥有的票数选择一个且只有一个随机赢家(使用RAND()就足够了)。可能有数百万行,因此循环是不可能的。如何使用T-SQL绘制胜利者?

2 个答案:

答案 0 :(得分:1)

此查询会根据票证总数找到一个随机数:

rand() * (select sum(tickets) from @TicketHolder)

您可以将其与运行总和查询结合使用,以查找绘制随机数的块的所有者:

select  top 1 t1.Name
from    @TicketHolder t1
where   (
        select  sum(Tickets)
        from    @TicketHolder t2
        where   t2.Name <= t1.Name
        ) > rand() * (select sum(tickets) from @TicketHolder)
order by
        t1.Name

Example at SE Data.在SE数据上,它总是选择相同的获胜者,可能是因为他们以固定方式播种rand()。如果我在本地运行它,它可以正常工作。

答案 1 :(得分:0)

修改您的表变量以包含RunningCount列:

DECLARE @TicketHolder TABLE (     
    [Name] VARCHAR(100),     
    Tickets DECIMAL(18, 8),
    RunningCount decimal(18,8)
);

添加票证数据:

INSERT INTO @TicketHolder ([Name], Tickets) 
SELECT 'Bob', 10.37 
UNION ALL 
SELECT 'Lisa', 1 
UNION ALL 
SELECT 'Robbie', 150.981 
UNION ALL 
SELECT 'Cathy', 97.888531; 

构建所有已购买门票的总计,并使用计数更新表格:

declare @RunningCount decimal(18,8) = 0

update @TicketHolder 
set 
    @RunningCount = @RunningCount + Tickets,
    RunningCount = @RunningCount

计算中奖彩票号

declare @WinningCount decimal(18,8) = @RunningCount * rand()

选择获胜者:

select top 1
    @WinningCount,
    Name
from
    @TicketHolder
where
    RunningCount <= @WinningCount
order by
    RunningCount desc