【问题标题】:Where is the official documentation for T-SQL's "ORDER BY RAND()" and "ORDER BY NEWID()"?T-SQL 的“ORDER BY RAND()”和“ORDER BY NEWID()”的官方文档在哪里?
【发布时间】:2014-01-31 18:33:15
【问题描述】:

我正在寻找“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 中的 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() 返回一个唯一标识符。
假设唯一标识符以数字方式进行比较似乎是合理的,所以如果 expression 是 NEWID() 我们的 将是一个

类似地,RAND() 返回一个数值,它也会被计算为一个。

因此,虽然我无法在 Microsoft 的官方文档中找到任何解释 ORDER BY 在使用作为 表达式 的 order_by_expression 调用时的作用的任何内容,但它确实被记录在案,因为我知道它一定是。

【问题讨论】:

  • 当您可以简单地测试它是否允许时,为什么还需要官方文档?
  • 这对我来说很奇怪。一方面,你想要微软的官方文档,而你出于某种原因添加到问题中的“答案”引用了来自我从未听说过的公司的某个域名的一些文档,我什至不想去下载。接下来,我不确定您在该文档中确定的尚未向您解释的内容。最后,您的解释忽略了不同表达式行为不同的事实(例如,rand() 不会按行计算)。
  • @Anechoic 您最近添加的新编辑部分看起来像一个答案,而不是一个问题。因此,请将其从此处删除并将其添加为答案
  • 我(个人)不认为它回答了你提出的原始问题,但它是一个答案,它不应该是问题的一部分。

标签: sql-server tsql random sql-order-by newid


【解决方案1】:

如果您试图确定为什么这些行为不同,原因很简单:一个被评估一次,并被视为运行时常量 (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 Sort,如果使用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();

计划:

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

我不知道这个具体的实现细节是否在任何地方都有正式记录,尽管我确实找到了this article,其中包含一个明确的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

在我的机器上,这需要大约 15 秒才能运行,MINMAX 的结果始终相同。不断增加返回的行数和所需的时间,我保证您将继续在每一行上看到完全相同的 RAND() 值。它只计算一次,这并不是因为 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

【讨论】:

  • 是 RAND 只计算一次,还是时间种子值在该执行时间内没有增加?
  • Repetitive calls of RAND() with the same seed value return the same results. 和`如果未指定种子,SQL Server 数据库引擎会随机分配来自here 的种子值`似乎表明该值不是静态的,除非您提供种子.
  • @asawyer 你真的应该把它读成a seed,而不是a seed per row
  • 啊,好吧,我明白你的意思了。感谢您为我澄清这一点!
  • @Anechoic 抱歉,但这些都与您将要获得的一样接近。 They don't officially list those expressions explicitly, they just say ORDER BY order_by_expression。当您查看像 INT 这样的数据类型的文档时,您是否需要他们明确列出 42 作为可能的值,以便您相信您可以将 42 存储在 INT 中?
【解决方案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 - NEWID

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

【讨论】:

  • 这些答案很有用,但不能回答我的问题(请参阅原帖)。
  • 我找到了我要找的东西。我已经发布了一个指向我已添加到原始帖子中的 ANSWER 部分的链接。
【解决方案3】:

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

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

基本上,

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

【讨论】:

  • 我认为是一个清晰、重点突出的问题显然不是,所以我修改了我之前的说明以更准确。这是 ORDER BY 的文档:[technet.microsoft.com/en-us/library/ms188385.aspx] 它解释了当您使用非负整数或字符串文字列表来指定列名时会发生什么。它没有解释如果您使用 表达式 会发生什么。 expression 实际作用的文档在哪里?
  • 我现在明白你的意思了。但除了它是“对查询结果集进行排序”的表达式。你不会找到你要找的东西。
  • 所以“说 X 的文档在哪里”的答案仍然是“无处”。
  • 我完全被这个难住了。文档没有解释对表达式的查询结果集进行排序意味着什么,其他人似乎都很好。那么,告诉我,如果我使用像 'CEILING(RAND() + .5) / 2' 这样的表达式(返回 0.5 或 1)会发生什么?你是怎么知道答案的(不是通过实验)?如果它没有在某处定义,怎么会有人知道如何正确使用它?
  • 我认为整数与计算结果为整数的表达式不同是有区别的。按常数排序是没有意义的,这就是为什么没人关心的原因。这也是让 T-SQL 支持指示列的整数的原因。同样,没有人需要按 CAST(0.5 * 2.0 as int) 排序,因为这无关紧要。另外,我已经完成了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多