如何使用纯 SQL 选择 N 个随机行?

Posted

技术标签:

【中文标题】如何使用纯 SQL 选择 N 个随机行?【英文标题】:How to select N random rows using pure SQL? 【发布时间】:2010-09-28 15:46:57 【问题描述】:

我们如何结合How to request a random row in SQL? 和Multiple random values in SQL Server 2005 使用单个纯SQL 查询选择N 个随机行?理想情况下,如果可能,我想避免使用存储过程。这甚至可能吗?

澄清

    纯 SQL 是指尽可能接近 ANSI/ISO 标准。 解决方案应该“足够高效”。授予 ORDER BY RAND() 可能有效,但正如其他人指出的那样,这对于中型表是不可行的。

【问题讨论】:

【参考方案1】:

您的问题的答案在第二个链接中:

SELECT * FROM table ORDER BY RAND() LIMIT 1

只需更改限制,和/或重写 SQL Server:

SELECT TOP 1 * FROM table ORDER BY newid()

现在,这个严格回答了你的问题,但你真的不应该使用这个解决方案。只需在一张大桌子上试一试,您就会明白我的意思。

如果您的键空间是连续的,要么没有孔,要么只有很少的孔,并且如果它的孔很少,您不必太担心某些行被选中的机会比其他行略高,那么您可以使用变体计算要随机检索的键,范围从 1 到表中的最高键,然后检索键等于或大于您计算的数字的第一行。如果您的键空间有孔,您只需要“高于”部分。

此 SQL 留给读者作为练习。


编辑:请注意,此处对另一个答案的评论提到,pure SQL 可能意味着 ANSI 标准 SQL。如果是这样,那就没有办法了,因为没有标准化的随机函数,也不是每个数据库引擎都以相同的方式对待随机数函数。我见过的至少一个引擎通过调用一次并为所有行重复计算值来“优化”调用。

【讨论】:

NEWID() 如果您想要真正的随机样本,这是一个坏主意,GUID 有很多结构。如果您不在乎是否真的很随机​​,请继续。【参考方案2】:

我不了解纯 ANSI,这并不简单,但您可以在此处查看我对类似问题的回答: Simple Random Samples from a Sql database

【讨论】:

如果假设 #3 为假(即您的桌子有孔),我不清楚如何实施您的建议。 你必须重写整个表,所以假设 #3 是正确的,所以这是一个非常慢的 O(n) 操作。创建一个与原始表具有相同列的新表,以及一个没有间隙的新主键的标识列。然后将整个原始表插入到新表中。【参考方案3】:

这是一个潜在的解决方案,它可以让您在获得少于 N 行的风险与表格“前面”的抽样偏差之间取得平衡。这假设 N 与表的大小相比较小:

select * from table where random() < (N / (select count(1) from table)) limit N;

这通常会对表的大部分进行采样,但可以返回少于 N 行。如果有一些偏差是可以接受的,那么分子可以从 N 更改为 1.5*N 或 2*N 以使返回 N 行的可能性很大。此外,如果需要随机化行顺序,而不仅仅是选择一个随机子集:

select * from (select * from table
                where random() < (N / (select count(1) from table)) limit N)
 order by mod(tableid,1111);

这个解决方案的缺点是,至少在 PostgreSQL 中,它使用表的顺序扫描。较大的分子会加快查询速度。

【讨论】:

【参考方案4】:

这可能对你有帮助:

SELECT TOP 3 * FROM TABLE ORDER BY NEWID()

【讨论】:

-1,已被 ***.com/a/396946/14731 覆盖,并且不是纯 SQL(newid() 是 Microsoft 特有的)。【参考方案5】:

使用下面的代码,您可以达到您想要的效果..

select top 1 * from student1 order by newid()

将 N 的值更改为前 1,这样您将收到该数量的随机记录。

【讨论】:

-1,已经被 ***.com/a/396946/14731 覆盖并且不是纯 SQL(newid() 是 Microsoft 特有的)。

以上是关于如何使用纯 SQL 选择 N 个随机行?的主要内容,如果未能解决你的问题,请参考以下文章

sql [sql]从每个类别中选择1个随机行

Hibernate Criteria API:获取 n 个随机行

选择 n 个随机行,其中 n 与每个值占总人口的百分比成比例

将一个表中的单行连接到另一个表中的 n 个随机行

MySQL 从 600K 行中快速选择 10 个随机行

如何从没有数字主键的表中有效地选择随机行