在SQL Server中选择N个随机记录而不重复

时间:2011-04-24 17:36:22

标签: sql sql-server fluent-nhibernate random unique

如何一次从表中选择N个随机记录而不重复先前由同一操作返回的记录?

一个明显的解决方案是:

SELECT TOP 5 * FROM
MyTable
WHERE Id NOT IN (SELECT Id FROM PreviouslyReturned)
ORDER BY newid()

但是,当MyTable开始增长时,这不会真的效率低下吗?

我有很长的记录列表,我一次需要五个记录来进行回合制游戏而不重复已经为给定游戏提取的任何记录。因为我知道大约会发生多少次转弯,所以我可以在游戏开始之前选择一个非常大的随机样本,但我宁愿它是“动态的”。我找到this question,它使用随机种子与MySQL。

最终将有如此多的记录,重复不会成为问题(记录>> N),但在此之前,我需要记录是唯一的。在旁注中,我使用Fluent NHibernate作为持久层;也许NHibernate有一些功能允许这个。

3 个答案:

答案 0 :(得分:2)

  

不重复任何记录

在程序员中没有被称为选择随机记录。随机选择的值比你想象的更频繁地重复,实际上计算重复次数和长度是统计学家检测作弊的一种方式。

您正在寻找的内容称为 shuffle 。随机抽样随机化一组有限的东西,如卡片或钥匙。 (随机化行的顺序与选择随机行的意义不同。)

在您的情况下,计划存储已为每个用户使用的密钥集。选择该组中尚未存在的随机行集。有几种方法可以存储每组随机行(键);确保您可以确定哪一个最后当前设置。

答案 1 :(得分:0)

尝试

SELECT TOP 5 *
FROM YOUR_TABLE
ORDER BY CHECKSUM(NEWID())

这里有一个相关的问题,详细介绍了随机随机选择的语义: Random select is not always returning a single row

SQL Server每个查询评估一次RAND,这意味着mySQL技巧无论如何都不会起作用。

编辑:这也足够了

SELECT TOP 5 *
FROM YOUR_TABLE
ORDER BY NEWID()

我阅读了您更新的问题并提出了另一个建议:

上创建索引视图
SELECT mt.*
FROM MyTable mt
LEFT JOIN PreviouslyReturned pr ON mt.Id = pr.Id
WHERE pr.Id Is NULL

或类似的东西

然后

SELECT TOP 5 *
FROM YOUR_INDEXED_VIEW
ORDER BY NEWID()

答案 2 :(得分:0)

您可以将表的所有主键存储在第二个表中,从该表中随机选择(从原始表中检索关联的行)并在选择后删除它们(当然,从辅助表中删除)。

我希望这种方式比存储已经使用的密钥和构造WHERE NOR IN(resp。EXCEPT)子句更有效(删除应该与插入一样高效,并且选择应该工作没有附加条款,显着更快)。但当然这必须得到证明(通过剖析......)

使用您引用的question中的方法,选择五个随机ID应该可以正常工作。