我在研究 SQL 时遇到了 TOP 语句。IE
SELECT TOP 2 * FROM Persons
从表 Persons 中选择最多 2 行。
但是,如果我出于统计原因使用它,我希望这样的过程是随机的:即独立于表中的时间和顺序。
我的问题是:
如何确保 TOP 语句是完全“随机的”(它的选择不是有序的)?此外,如何确保 TOP 语句是针对某些变量(即年龄)排序的
TOP 语句实际上是如何工作的?
我在研究 SQL 时遇到了 TOP 语句。IE
SELECT TOP 2 * FROM Persons
从表 Persons 中选择最多 2 行。
但是,如果我出于统计原因使用它,我希望这样的过程是随机的:即独立于表中的时间和顺序。
我的问题是:
如何确保 TOP 语句是完全“随机的”(它的选择不是有序的)?此外,如何确保 TOP 语句是针对某些变量(即年龄)排序的
TOP 语句实际上是如何工作的?
我假设您使用的是 SQL Server,因为这是我所知道的使用 SQL Server 的版本,
TOP
而不是LIMIT
.SQL Server 中的数据总是按某种顺序排列;
ORDER BY
但是,只有当您在 SQL 语句中包含一个子句时,才能保证该顺序是什么。如果没有
ORDER BY
子句,数据集的顺序由生成它所需的过程以及存储的顺序决定。如果一个表没有改变,并且您多次对其运行相同的 SQL 语句,您将以相同的顺序取回数据。这是因为查询引擎每次都应用相同的过程来生成结果数据集。
因此,如果您多次针对一个表发出查询(没有插入、更新或删除),您每次都会得到相同的 2 行。
注意:根据表的结构(例如,是否有聚集索引)和针对表的活动,您可能会在基本上不是静态
SELECT TOP 2 *
的表上给出不同的结果。这就是为什么您需要 an来保证顺序,即使今天运行的查询没有 an以您希望的顺序始终如一地返回数据。ORDER BY
ORDER BY
使用
TOP
andORDER BY
时,查询引擎必须至少对您的数据进行部分排序(如果它可以找到并排序前n行,则不必对其余行进行排序)。使用TOP
but notORDER BY
,它只选择它生成的数据集的前n行。如果你想要随机排序,你(听起来很奇怪)需要随机排序数据。
ORDER BY NEWID()
(正如Lamak在评论中所建议的那样)会这样做。NEWID()
每次运行时都会生成一个新的 GUID,并且不会以任何顺序生成这些 GUID。这个 SO 问题解释了它是如何工作的。它还描述了如何TOP
进一步工作。正如sp_BlitzErik指出的那样,
ORDER BY NEWID()
它并不快,而且表越大越慢(它必须为表中的每一行生成一个 GUID,而不管TOP
要返回的行数如何)。他链接到How to Get a Random Row from a Large Table,这是他公司网站上的一篇文章,以获取有关从表中获取真正随机行的更多建议。基本上,选项是使用一个相对晦涩的查询选项,称为
TABLESAMPLE
,这可能会出现问题;或者,使用该RAND
函数生成一个随机 ID 值以返回一行(如果您需要多于一两行,或者每次运行时需要可变数量的行,则将随机数转储到临时表中)。您还可以使用RAND
withOFFSET ... FETCH
子句在 SQL 2012 或更高版本中获取单个随机行。