T-SQL的"ORDER BY RAND()"和"ORDER BY NEWID()"的官方文档在哪里?

Ane*_*oic -2 t-sql sql-server random sql-order-by newid

我正在寻找"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>.
Run Code Online (Sandbox Code Playgroud)

此时我们得到了答案的前半部分:

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
Run Code Online (Sandbox Code Playgroud)

这需要我们:

6.25 <value expression>
Run Code Online (Sandbox Code Playgroud)

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

<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>
Run Code Online (Sandbox Code Playgroud)

从这里我们可以看到可以使用的众多可能类型的表达式.

NEWID()返回一个uniqueidentifier.
假设uniqueidentifier在数值上进行比较似乎是合理的,因此如果expression是NEWID(),则我们的<common value expression>将是<numeric value expression>.

类似地,RAND()返回一个数值,它也将被计算为<数值表达式>.

因此,虽然我无法在Microsoft的官方文档中找到任何解释使用order_by_expression作为表达式调用时ORDER BY所执行操作的内容,但我确实记录了它,因为我知道它必须如此.

Aar*_*and 8

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

SELECT TOP (5) RAND(), NEWID() FROM sys.objects;
Run Code Online (Sandbox Code Playgroud)

结果:

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
Run Code Online (Sandbox Code Playgroud)

现在,如果您将订单应用到左列,SQL Server说,好的,但每个值都相同,所以我基本上只是忽略您的请求并转到下一个ORDER BY列.如果没有,则SQL Server将默认以其认为最有效的顺序返回行.

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

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

SELECT RAND() FROM sys.all_columns ORDER BY RAND();
Run Code Online (Sandbox Code Playgroud)

计划:

在此输入图像描述

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

现在NEWID():

SELECT NEWID() FROM sys.all_columns ORDER BY NEWID();
Run Code Online (Sandbox Code Playgroud)

计划:

在此输入图像描述

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

我不知道这个具体的实现细节是在任何地方正式记录的,尽管我确实发现这篇文章包括一个明确的ORDER BY NEWID().我怀疑你会ORDER BY RAND()以任何方式找到任何正式的文件,因为这没有任何意义,官方支持与否.

Re: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);
Run Code Online (Sandbox Code Playgroud)

结果:

0.4866202638872        0.4866202638872
Run Code Online (Sandbox Code Playgroud)

在我的机器,这花了约15秒的运行,其结果总是上是相同的MINMAX.继续增加返回的行数和所需的时间,我保证你会继续看到RAND()每行的完全相同的值.它只计算一次,这不是因为SQL Server明智的是我没有返回所有的行.这也产生了相同的结果(用不到2分钟的时间用整个表填充7200万行):

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;
Run Code Online (Sandbox Code Playgroud)

(实际上这SELECT几乎和初始人口一样长.请不要在配备4GB内存的单核笔记本电脑上试试这个.)

结果:

0.302690214345828        0.302690214345828
Run Code Online (Sandbox Code Playgroud)