如何在纯SQL中请求随机行(或尽可能接近真正的随机)?
当前回答
像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)范围内均匀分布。如果您的数据集严重偏离这个假设,您将得到倾斜的结果(一些行会比其他行出现得更频繁)。
其他回答
你没说你用的是哪台服务器。在旧版本的SQL Server中,你可以使用这个:
select top 1 * from mytable order by newid()
在SQL Server 2005及以上版本中,你可以使用TABLESAMPLE来获取一个可重复的随机样本:
SELECT FirstName, LastName
FROM Contact
TABLESAMPLE (1 ROWS) ;
select r.id, r.name from table AS r
INNER JOIN(select CEIL(RAND() * (select MAX(id) from table)) as id) as r1
ON r.id >= r1.id ORDER BY r.id ASC LIMIT 1
这将需要更少的计算时间
ORDER BY NEWID()
耗时7.4毫秒
WHERE num_value >= RAND() * (SELECT MAX(num_value) FROM table)
只需要0.0065毫秒!
我肯定会选择后一种方法。
我还没看出来答案有什么不同。我有一个额外的约束条件,给定一个初始种子,每次都要选择相同的行集。
对于MS SQL:
最小的例子:
select top 10 percent *
from table_name
order by rand(checksum(*))
规范化执行时间:1.00
NewId()例子:
select top 10 percent *
from table_name
order by newid()
规范化执行时间:1.02
NewId()比rand(checksum(*))慢不了多少,所以您可能不希望对大型记录集使用它。
初始种子选择:
declare @seed int
set @seed = Year(getdate()) * month(getdate()) /* any other initial seed here */
select top 10 percent *
from table_name
order by rand(checksum(*) % seed) /* any other math function here */
如果给定一个种子,你需要选择相同的集合,这似乎是可行的。
SELECT * FROM table ORDER BY RAND() LIMIT 1
推荐文章
- 使用该集合的原因。种子功能
- GROUP BY with MAX(DATE)
- 删除id与其他表不匹配的sql行
- 等价的限制和偏移SQL Server?
- 为什么我不能在DELETE语句中使用别名?
- 在SQL Server Management Studio中保存带有标题的结果
- "where 1=1"语句
- 如何选择一个记录和更新它,与一个单一的查询集在Django?
- 多语句表值函数vs内联表值函数
- 如何从Oracle的表中获取列名?
- NOLOCK提示在SELECT语句中的作用
- SQL OVER()子句-它什么时候有用,为什么有用?
- 如果字段在MySQL中为空,则返回0
- 从枚举中选择一个随机值?
- 我如何使用ROW_NUMBER()?