-2

我正在寻找“ORDER BY RAND()”和“ORDER BY NEWID()”的官方 T-SQL 文档。有许多文章描述了它们,因此必须在某个地方记录它们。

我正在寻找这样的官方 SQL Server 文档页面的链接: http ://technet.microsoft.com/en-us/library/ms188385.aspx

澄清:

我正在寻找的是“order_by_expression”的文档,它解释了非负整数常量、返回非负整数的函数和返回任何其他值的函数(如 RAND() 或 NEWID() )。


回答:

我为我最初的问题缺乏明确性表示歉意。与大多数与编程相关的问题一样,该问题的解决方案主要是弄清楚您实际上要回答什么问题。

谢谢大家。


答案在本文档中:来自: http: //www.wiscorp.com/sql200n.zip

Information technology — Database languages — SQL — Part 2: Foundation (SQL/Foundation)

22.2 <direct select statement: multiple rows> includes a <cursor specification>.

至此,我们有了答案的前半部分:

SELECT 语句是一种 CURSOR,这意味着可以在每一行上迭代地执行操作。尽管我没有在文档中找到明确说明的语句,但我很乐意假设 order_by_expression 中的表达式将为每一行执行。

现在,当您使用 RAND() 或 NEWID() 或 CEILING(RAND() + .5) / 2 而不是数字常量或列名时,发生了什么是有意义的。
表达式永远不会被视为列号。它始终是为每一行生成的值,将用作确定行顺序的基础。

但是,为了彻底起见,让我们继续对表达式的完整定义。

14.3 <cursor specification> includes ORDER BY <sort specification list>.

10.10 <sort specification list> defines:

<sort specification> ::= <sort key> [ <ordering specification> ] [ <null ordering> ]
    <sort key> ::= <value expression>
    <ordering specification> ::= ASC | DESC
    <null ordering> ::= NULLS FIRST | NULLS LAST

这将我们带到:

6.25 <value expression>

我们在哪里找到答案的后半部分:

<value expression> ::= 
      <common value expression> 
    | <boolean value expression> 
    | <row value expression>

<common value expression> ::= 
      <numeric value expression> 
    | <string value expression>
    | <datetime value expression>
    | <interval value expression>
    | <user-defined type value expression>
    | <reference value expression>
    | <collection value expression>

    <user-defined type value expression> ::= <value expression primary>
    <reference value expression> ::= <value expression primary>
    <collection value expression> ::= <array value expression> | <multiset value expression>

从这里我们深入到可以使用的众多可能的表达式类型。

NEWID() 返回一个唯一标识符。
假设唯一标识符以数字方式进行比较似乎是合理的,因此如果表达式是 NEWID(),我们的 <common value expression> 将是一个 <numeric value expression>。

类似地,RAND() 返回一个数值,它也将被评估为一个<数值表达式>。

因此,尽管我无法在 Microsoft 的官方文档中找到任何解释 ORDER BY 在使用作为表达式的 order_by_expression 调用时的作用的任何内容,但它确实已记录在案,因为我知道它必须如此。

4

3 回答 3

8

如果您试图确定这些行为不同的原因,原因很简单:一个被评估一次,并被视为运行时常量(RAND()),而另一个被评估为每一行(NEWID())。观察这个简单的例子:

SELECT TOP (5) RAND(), NEWID() FROM sys.objects;

结果:

0.240705716465209        8D5D2B55-E5DE-4FF9-BA84-BC82F37B8F3A
0.240705716465209        C4CBF1CA-E6D0-4076-B6A6-5048EA612048
0.240705716465209        9BFAE5BB-B5B9-47DE-B8F9-77AAEFA5F9DB
0.240705716465209        89FFD8A1-AC73-4CEB-A5C0-00A76D040382
0.240705716465209        BCC89923-735E-43B3-9ECA-622A8C98AD7D

现在,如果您将 order by 应用于左列,SQL Server 会说,好的,但是每个值都是相同的,所以我基本上只是忽略您的请求并继续下一个 ORDER BY 列。如果没有,则 SQL Server 将默认以它认为最有效的任何顺序返回行。

如果将 order by 应用于右列,现在 SQL Server 实际上必须对所有值进行排序。这会在计划中引入Sort(或使用TopN Sortif TOP)运算符,并且可能会占用更多 CPU(尽管总体持续时间可能不会受到实质性影响,具体取决于集合的大小和其他因素)。

让我们比较一下这两个查询的计划:

SELECT RAND() FROM sys.all_columns ORDER BY RAND();

计划:

在此处输入图像描述

没有排序运算符在进行,并且两次扫描都是Ordered = False- 这意味着 SQL Server 尚未决定显式实现任何排序,但这当然并不意味着每次执行的顺序都会有所不同 - 它只是意味着顺序是不确定的(除非您添加辅助项ORDER BY- 但即使在这种情况下,RAND()顺序仍然会被忽略,因为它在每一行上都是相同的值)。

现在NEWID()

SELECT NEWID() FROM sys.all_columns ORDER BY NEWID();

计划:

在此处输入图像描述

那里有一个 newSort运算符,这意味着 SQL Server 必须按照每行上生成的 GUID 值的顺序重新排序要返回的所有行。当然,扫描仍然是无序的,但Sort最终会应用该顺序。

我不知道这个具体的实现细节在任何地方都有正式记录,尽管我确实找到了这篇文章,其中包含一个明确的ORDER BY NEWID(). 我怀疑您会以任何方式找到任何官方文件ORDER BY RAND(),因为无论是否得到官方支持,这样做都没有任何意义。

回复:SQL Server 分配的注释a seed value at random- 这不应被解释为a seed value **per row** at random. 示范:

SELECT MAX(r), MIN(r) FROM 
(
  SELECT RAND() FROM sys.all_columns AS s1 
  CROSS JOIN sys.all_columns AS s2
) AS x(r);

结果:

0.4866202638872        0.4866202638872

MIN在我的机器上,这需要大约 15 秒的时间来运行,并且对于和的结果总是相同的MAXRAND()不断增加返回的行数和所需的时间,我保证您将继续在每一行上看到完全相同的值。它只计算一次,这并不是因为 SQL Server 明智地认识到我没有返回所有行。这也产生了相同的结果(用 7200 万行填充整个表只用了不到 2 分钟):

SELECT RAND() AS r INTO #x 
      FROM sys.all_columns AS s1 
CROSS JOIN sys.all_columns AS s2
CROSS JOIN sys.all_columns AS s3;

SELECT MAX(r), MIN(r) FROM #x;

(事实上​​,这SELECT几乎和最初的人口一样长。不要在具有 4GB RAM 的单核笔记本电脑上尝试这个。)

结果:

0.302690214345828        0.302690214345828
于 2014-01-31T18:54:50.770 回答
2

如果我们是对细节的坚持者,那么您提出的问题本质上是“〜的文档在哪里”。答案无处可寻,没有像您要找的那样的文档。

反正不是一个,有多个文档分别处理 NEWID()、RAND() 和 ORDER BY,你必须自己把这些部分放在一起。

基本上,

这让您知道它是有效的语法,但没有单个链接可供您指向。

于 2014-02-06T22:10:00.190 回答
2

检查下方的链接。

ORDER BY、RAND 和 NEWID 是 TSQL 语言的语句和函数的一部分。

将它们组合起来随机选择或生成数据是一种设计模式。

见前两篇文章。

生成无冲突的随机整数

http://www.sqlperformance.com/2013/09/t-sql-queries/random-collisions

MSDN - 从大表中随机选择行

http://msdn.microsoft.com/en-us/library/cc441928.aspx

MSDN-兰德

http://technet.microsoft.com/en-us/library/ms177610.aspx

MSDN-新ID

http://msdn.microsoft.com/fr-fr/library/ms190348.aspx

MSDN - 订购者

http://technet.microsoft.com/en-us/library/ms188385.aspx

很好读亚伦。

但同样,单独(RAND、NEWID、ORDER BY)是TSQL 语言的元素部分。

使用它们随机选择数据是一种设计模式

此外,您可以在 while 循环中调用 RAND() - RBAR() 产生随机数。

这是因为在查询计划中,RAND() 不再是一个常数。

-- RBAR solution
declare @x float = 0;
declare @y int = 0;
while (@y < 100)
begin
    set @x = rand();
    print @x;
    set @y += 1;
end;
go

在此处输入图像描述

于 2014-01-31T18:45:52.273 回答