Sql server it:只是在一个更大的数据集上进行了测试。它不工作,因为它返回所有行,而不仅仅是顶部5@EdmCoff我刚刚发现,在一个更大的数据集上,上述方法并没有像预期的那样有效。是的,我希望有更多门票的用户有更高的机会被选中。然而,它不应该像拥有最高票数的用户总是首
Sql server it:只是在一个更大的数据集上进行了测试。它不工作,因为它返回所有行,而不仅仅是顶部5@EdmCoff我刚刚发现,在一个更大的数据集上,上述方法并没有像预期的那样有效。是的,我希望有更多门票的用户有更高的机会被选中。然而,它不应该像拥有最高票数的用户总是首,sql-server,distinct,Sql Server,Distinct,it:只是在一个更大的数据集上进行了测试。它不工作,因为它返回所有行,而不仅仅是顶部5@EdmCoff我刚刚发现,在一个更大的数据集上,上述方法并没有像预期的那样有效。是的,我希望有更多门票的用户有更高的机会被选中。然而,它不应该像拥有最高票数的用户总是首先被选中一样。它必须仍然是随机的,就像彩票一样:-)我已经更新了解决方案,你能检查一下吗。如果不起作用,请提供一些示例数据和预期数据。我认为混淆之处在于,此解决方案需要在顶部显示“top 5”,并在主查询中显示另一个“ORDER BY NEWI
it:只是在一个更大的数据集上进行了测试。它不工作,因为它返回所有行,而不仅仅是顶部5@EdmCoff我刚刚发现,在一个更大的数据集上,上述方法并没有像预期的那样有效。是的,我希望有更多门票的用户有更高的机会被选中。然而,它不应该像拥有最高票数的用户总是首先被选中一样。它必须仍然是随机的,就像彩票一样:-)我已经更新了解决方案,你能检查一下吗。如果不起作用,请提供一些示例数据和预期数据。我认为混淆之处在于,此解决方案需要在顶部显示“top 5”,并在主查询中显示另一个“ORDER BY NEWID()”。但这仍然不会使它选择1000张票证的用户的频率高于选择1张票证的用户的频率。我认为这不符合评论中(新增)的要求,即选择1000张票证的用户的概率应高于选择1张票证的用户的概率。编辑:只是在一个更大的数据集上测试它。它不工作,因为它返回所有行,而不仅仅是顶部5@EdmCoff我刚刚发现,在一个更大的数据集上,上述方法并没有像预期的那样有效。是的,我希望有更多门票的用户有更高的机会被选中。然而,它不应该像拥有最高票数的用户总是首先被选中一样。它必须仍然是随机的,就像彩票一样:-)我已经更新了解决方案,你能检查一下吗。如果不起作用,请提供一些示例数据和预期数据。我认为混淆之处在于,此解决方案需要在顶部显示“top 5”,并在主查询中显示另一个“ORDER BY NEWID()”。但是这仍然不会使它选择一个拥有1000张票证的用户的频率比选择一个拥有1张票证的用户的频率更高。嘿,Steve,我刚刚试过运行你的查询,但是在一个拥有100万条记录的测试表中,它总是只返回5张相同的票证。
ROW_NUMBER()OVER(ORDER BY RAND()ASC)作为随机顺序
这行不通。RAND()
函数在每个查询中执行一次。您需要一个每行执行一次的函数,如NEWID()
执行。@BaconBits,同意@Klatzen,我已经调整了查询以修复。请注意我对埃德姆科夫回答的评论。@Steve。今天早上刚测试过它,它似乎成功了!嘿,Steve,我刚刚试着运行你的查询,但是在一个有一百万条记录的测试表中,它总是只返回5条相同的票证。ROW\u NUMBER()OVER(ORDER BY RAND()ASC)AS random\u ORDER
这行不通。RAND()
函数在每个查询中执行一次。您需要一个每行执行一次的函数,如NEWID()
执行。@BaconBits,同意@Klatzen,我已经调整了查询以修复。请注意我对埃德姆科夫回答的评论。@Steve。今天早上刚测试过它,它似乎成功了!嘿,大卫。我尝试输入您的查询,但它找不到“如果存在”?可能与我正在运行的SQL server版本有关吗?是的。SQL 2016中引入了DROP TABLE IF EXISTS。如果这是一个存储过程,只需省略DROP表即可。程序结束时会自动删除临时表。啊,好的。只是为了学习,在性能不好的情况下不使用吗?性能始终是“足够好”的问题,这个问题需要某种多通道方法。嘿,大卫。我尝试输入您的查询,但它找不到“如果存在”?可能与我正在运行的SQL server版本有关吗?是的。SQL 2016中引入了DROP TABLE IF EXISTS。如果这是一个存储过程,只需省略DROP表即可。程序结束时会自动删除临时表。啊,好的。只是为了学习,在性能方面使用while不是很糟糕吗?性能始终是“足够好”的问题,这个问题需要某种多通道方法。在100万行和只有4行的表上测试了它,其中只有两行具有唯一的userId。它似乎像我希望的那样工作。非常感谢你!选择这个作为工作答案:-)如果这是为了任何重要的事情,或者如果奖品很重要,我不会依赖NEWID()
。我将使用CRYPT\u GEN\u RANDOM(16)
(或其他长度),它从加密API位生成数字。谢谢你的提醒,我一定会调查的。@EdmCoff,谢谢你的提醒!正如我所说,我没有测试我的代码。我对您的方法的唯一观察是,它不会保留多张票子的权重,因为它会在选择赢家之前(按照NEWID()的最终顺序)(
)消除它们(随机选择受害者票子)。我的代码首先选择中奖彩票的顺序,并且只删除那些在最终输出中代表第二次胜利的彩票(中奖顺序通过在所有彩票仍然存在于集合中的第一轮进行维护)。@steve谢谢。我编辑了这篇文章来警告人们这一点。我想我对简化我的答案有点太着迷了。在100万行和一个只有4行的表上测试了它,其中只有两行有唯一的userId。它似乎像我希望的那样工作。非常感谢你!选择这个作为工作答案:-)如果这是为了任何重要的事情,或者如果奖品很重要,我不会依赖NEWID()
。我将使用CRYPT\u GEN\u RANDOM(16)
(或其他长度),它从加密API位生成数字。谢谢你的提醒,我一定会调查的。@EdmCoff,谢谢你的提醒!正如我所说,我没有测试我的代码。我对您的方法的唯一观察是,它不会保留多张票子的权重,因为它会在选择赢家之前(按照NEWID()的最终顺序)(
)消除它们(随机选择受害者票子)。
ticketId, userId
SELECT TOP 5 *
FROM Tickets
ORDER BY RAND(CHECKSUM(*) * RAND())
Ticket id: UserId:
--------------------------
10 1
25 1
31 2
42 2
56 3
Select UserId
from
(
SELECT TOP 5 UserId
FROM Tickets
ORDER BY NEWID()
)k
CROSS APPLY
(
select top 1 TicketId
from Tickets T WHERE T.UserId = k.UserId
ORDER BY NEWID()
)u
WITH randomised_tickets AS
(
SELECT
*
,ROW_NUMBER() OVER (ORDER BY NEWID() ASC) AS random_order
FROM Tickets
)
,ordered_winning_tickets AS
(
SELECT
*
,ROW_NUMBER() OVER (PARTITION BY userId ORDER BY random_order ASC) AS user_win_order
FROM randomised_tickets
)
SELECT TOP 5
*
FROM
ordered_winning_tickets
WHERE
user_win_order = 1 --eliminate 2nd wins from the list
ORDER BY
random_order
drop table if exists #WinningTickets
create table #WinningTickets(PickId int identity primary key, TicketId int, UserId int)
create unique index ix_unique_user on #WinningTickets(UserId) with (ignore_dup_key=on)
while ( select count(*) from #WinningTickets ) < 5
begin
insert into #WinningTickets
select top 10 TicketId, UserId
from Tickets
order by newid()
end
select top 5 *
from #WinningTickets
order by PickId
SELECT top 5 ticketid, userid
FROM
(
SELECT ticketid, userid, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY NEWID()) as nid
FROM tickets
) a
WHERE nid = 1
ORDER BY NEWID()