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

时间:2014-01-31 18:33:15

标签: sql-server tsql 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>.

此时我们有答案的前半部分:

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()返回一个uniqueidentifier 假设uniqueidentifier在数字上进行比较似乎是合理的,因此如果表达式是NEWID(),则我们的&lt;公共值表达式&gt;将是&lt;数值表达式&gt;
同样,RAND()返回一个数值,它也将被评估为&lt;数值表达式&gt;。

因此,虽然我无法在Microsoft的官方文档中找到任何解释使用作为表达式的order_by_expression调用的ORDER BY所做的事情,但它确实已经记录,因为我知道它必须是。

3 个答案:

答案 0 :(得分:8)

如果你试图确定为什么这些行为不同,原因很简单:一个被评估一次,被视为运行时常量(RAND()),而另一个被评估为每一行({ {1}})。请注意这个简单的例子:

NEWID()

结果:

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

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

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

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

TOP

计划:

  

enter image description here

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

现在RAND()

NEWID()

计划:

  

enter image description here

那里有一个新的SELECT NEWID() FROM sys.all_columns ORDER BY NEWID(); 运算符,这意味着SQL Server必须按照每行上生成的GUID值的顺序重新排序要返回的所有行。当然扫描仍然是无序的,但Sort最终会应用订单。

我不知道这个具体的实现细节是在任何地方正式记录的,但我确实发现this article包含一个明确的Sort。我怀疑你会发现任何以任何方式记录ORDER BY NEWID()的官方文件,因为这没有任何意义,官方支持与否。

Re:SQL Server分配的注释ORDER BY RAND() - 这不应该被解释为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);

在我的计算机上,这需要大约15秒才能运行,0.4866202638872 0.4866202638872 MIN的结果始终相同。继续增加返回的行数和所花费的时间,我保证您将继续在每一行上看到MAX的完全相同的值。它只计算一次,这不是因为SQL Server明智的是我没有返回所有的行。这也产生了相同的结果(用不到2分钟的时间用整个表填充7200万行):

RAND()

(实际上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; 的使用时间几乎和初始人口一样长。请不要在配备4GB RAM的单核笔记本电脑上试试这个。)

结果:

SELECT

答案 1 :(得分: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 - RAND

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

MSDN - NEWID

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

MSDN - ORDER BY

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

非常好读Aaron。

但是,另外,单独采用(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

enter image description here

答案 2 :(得分:2)

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

无论如何,有多个文档分别处理NEWID(),RAND()和ORDER BY,你必须自己把它们放在一起。

基本上,

这让你知道它是有效的语法,但没有一个链接供你指出。