如何在纯SQL中请求随机行(或尽可能接近真正的随机)?
当前回答
在SQL Server中,您可以将TABLESAMPLE与NEWID()结合使用,以获得相当好的随机性,并且仍然具有速度。如果您真的只想要1行或少量的行,这尤其有用。
SELECT TOP 1 * FROM [table]
TABLESAMPLE (500 ROWS)
ORDER BY NEWID()
其他回答
火鸟:
Select FIRST 1 column from table ORDER BY RAND()
最好的方法是在新列中放入一个随机值,并使用如下代码(伪代码+ SQL):
randomNo = random()
execSql("SELECT TOP 1 * FROM MyTable WHERE MyTable.Randomness > $randomNo")
这是MediaWiki代码采用的解决方案。当然,对于较小的值会有一些偏差,但他们发现,在没有获取行的情况下,将随机值包装为0就足够了。
Newid()解决方案可能需要全表扫描,以便为每一行分配一个新的guid,这将大大降低性能。
rand()解决方案可能根本不起作用(即与MSSQL),因为函数将只计算一次,并且每一行将被分配相同的“随机”数字。
似乎列出的许多想法仍然使用排序
但是,如果使用临时表,则可以分配一个随机索引(就像许多解决方案所建议的那样),然后获取第一个大于0到1之间任意数字的索引。
例如(对于DB2):
WITH TEMP AS (
SELECT COMLUMN, RAND() AS IDX FROM TABLE)
SELECT COLUMN FROM TABLE WHERE IDX > .5
FETCH FIRST 1 ROW ONLY
像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)范围内均匀分布。如果您的数据集严重偏离这个假设,您将得到倾斜的结果(一些行会比其他行出现得更频繁)。
晚了,但通过谷歌到达这里,所以为了子孙后代,我将添加一个替代解决方案。
另一种方法是使用TOP两次,顺序交替。我不知道它是否是“纯SQL”,因为它在TOP中使用了一个变量,但它在SQL Server 2008中工作。这里有一个例子,如果我想要一个随机的单词,我使用字典单词表。
SELECT TOP 1
word
FROM (
SELECT TOP(@idx)
word
FROM
dbo.DictionaryAbridged WITH(NOLOCK)
ORDER BY
word DESC
) AS D
ORDER BY
word ASC
当然,@idx是目标表上从1到COUNT(*)的随机生成的整数。如果您的列被索引,您也会从中受益。另一个优点是可以在函数中使用它,因为NEWID()是不允许的。
最后,在同一个表上,上述查询的执行时间大约是NEWID()类型查询的1/10。YYMV。
推荐文章
- 有人可以对SQL查询进行版权保护吗?
- 如何知道MySQL表最近一次更新?
- 如何转储一些SQLite3表的数据?
- 如何创建一个SQL Server函数“连接”多行从一个子查询到一个单独的分隔字段?
- 在MySQL中的一个查询中更新多个具有不同值的行
- 在SQL中更新多个列
- 如何删除表中特定列的第一个字符?
- MySQL OR与IN性能
- 哪个更快/最好?SELECT *或SELECT columnn1, colum2, column3等
- 使用该集合的原因。种子功能
- GROUP BY with MAX(DATE)
- 删除id与其他表不匹配的sql行
- 等价的限制和偏移SQL Server?
- 为什么我不能在DELETE语句中使用别名?
- 在SQL Server Management Studio中保存带有标题的结果