如何在纯SQL中请求随机行(或尽可能接近真正的随机)?
当前回答
你没说你用的是哪台服务器。在旧版本的SQL Server中,你可以使用这个:
select top 1 * from mytable order by newid()
在SQL Server 2005及以上版本中,你可以使用TABLESAMPLE来获取一个可重复的随机样本:
SELECT FirstName, LastName
FROM Contact
TABLESAMPLE (1 ROWS) ;
其他回答
我不得不同意CD-MaN:使用“ORDER BY RAND()”将很好地用于小表或当你只做几次SELECT时。
我还使用“num_value >= RAND() *…”技术,如果我真的想获得随机结果,我在表中有一个特殊的“随机”列,我大约每天更新一次。单个UPDATE运行将花费一些时间(特别是因为必须在该列上建立索引),但它比每次运行select时为每一行创建随机数快得多。
像Jeremies这样的解决方案:
SELECT * FROM table ORDER BY RAND() LIMIT 1
工作,但是它们需要对所有表进行顺序扫描(因为需要计算与每一行相关联的随机值——这样才能确定最小的值),即使对于中等大小的表,这也是相当慢的。我的建议是使用某种索引数字列(许多表都将这些列作为主键),然后编写如下内容:
SELECT * FROM table WHERE num_value >= RAND() *
( SELECT MAX (num_value ) FROM table )
ORDER BY num_value LIMIT 1
如果num_value被索引,那么无论表大小如何,它都在对数时间内工作。注意:这里假设num_value在0..MAX(num_value)范围内均匀分布。如果您的数据集严重偏离这个假设,您将得到倾斜的结果(一些行会比其他行出现得更频繁)。
如果可能的话,使用存储语句来避免RND()上的索引和创建记录编号字段的效率低下。
PREPARE RandomRecord FROM "SELECT * FROM table LIMIT ?,1"; SET @n=FLOOR(RAND()*(SELECT COUNT(*) FROM table)); EXECUTE RandomRecord USING @n;
SELECT * FROM table ORDER BY RAND() LIMIT 1
使用SQL Server 2012+,您可以使用OFFSET FETCH查询对单个随机行执行此操作
select * from MyTable ORDER BY id OFFSET n ROW FETCH NEXT 1 ROWS ONLY
其中id是一个标识列,n是您想要的行—计算为表的0到count()-1之间的随机数(偏移量0毕竟是第一行)
这适用于表数据中的漏洞,只要您有一个用于ORDER BY子句的索引。它对随机性也很有好处——因为你可以自己计算出来传递进来,但其他方法中的琐碎问题是不存在的。此外,性能非常好,在一个较小的数据集上,它表现得很好,尽管我没有尝试过针对数百万行进行认真的性能测试。
推荐文章
- 如何在Ruby On Rails中使用NuoDB手动执行SQL命令
- 查询JSON类型内的数组元素
- 确定记录是否存在的最快方法
- 获得PostgreSQL数据库中当前连接数的正确查询
- 如何在Ruby中生成a和b之间的随机数?
- 在SQL选择语句Order By 1的目的是什么?
- 我如何循环通过一组记录在SQL Server?
- 如何从命令行通过mysql运行一个查询?
- 外键约束可能导致循环或多条级联路径?
- java.util.Random真的那么随机吗?我怎么能生成52!(阶乘)可能的序列?
- 使用LIMIT/OFFSET运行查询,还可以获得总行数
- 从数组中随机选择一个元素
- 当恢复sql时,psql无效命令\N
- 货币应该使用哪种数据类型?
- 如何选择每一行的列值不是独特的