ORDER BY ABS(CHECKSUM(NEWID())如何运作?

时间:2014-02-27 00:26:11

标签: sql sql-server sql-order-by

我偶然发现了一个随机代码ID生成器,我无法弄清楚它是如何工作的。

SELECT TOP (5) c1
FROM
  (
VALUES
  ('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ('G'),
  ('3'), ('4'), ('5'), ('6'), ('7'), ('8'), ('9')
  ) AS T1(c1)
ORDER BY ABS(CHECKSUM(NEWID()))

我看过以下内容:

  • 选择NEWID() - > E8E142CC-A918-4776-AA99-2D33DC80FE28
  • 选择CHECKSUM('E8E142CC-A918-4776-AA99-2D33DC80FE28') - > -2089106226
  • 选择ABS(-2089106226) - > 2089106226

如果我然后尝试做“按2089106226排序”,它显然会失败

那么什么是“ABS(CHECKSUM(NEWID())”返回以及这种类型的排序叫什么?

2 个答案:

答案 0 :(得分:5)

ORDER BY子句不必像您发现的那样对特定列进行排序,而是可以包含任意表达式。我不相信这有任何特殊名称,它只是order_by_expression documented here

ORDER BY部分中的动态值

ORDER BY中的非列表达式可能类似于

ORDER BY a_column % 5

根据列的值模数5或类似

对行进行排序
ORDER BY CASE WHEN LEFT(a_column, 1) = 'Z' THEN 0 ELSE 1 END ASC, a_column ASC

强制columnZ开头的所有值排在所有其他值之前,但在其他方面是按字母顺序排列的,方法是将0归为Z行{ {1}}否则(其中零排序)。

在这种情况下,表达式是在T-SQL中随机化行顺序的常用方法:

1

将为ABS(CHECKSUM(NEWID())) 语句返回的每一行调用NEWID()函数,这会产生5个单独的GUID值。从那里,这5个中的每一个都是passed to CHECKSUM(),它返回一个恰好是整数的索引哈希值。 SELECT最终迫使它成为一个正整数。

因此,最终发送到ABS()的值只是从多个ORDER BY调用派生的整数列表,而NEWID()排序整数没有问题。最后,它与排序整数值列并没有什么不同 - 只是这些是在查询时生成的。

如果您运行this demonstration on SQLFiddle几次,则会在每次执行时为其他增量ORDER BY获得不同的排序顺序。因此,看起来有问题的随机代码生成器SQL的作者使用id来混淆从ORDER BY列表中选择的5个字符的随机集合的原因。如果您run the code generator SQL并注释掉VALUES (),则会始终返回行集ORDER BY。在A,B,C,D,E到位后,它会返回一个随机集。

答案 1 :(得分:0)

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

但是从语法上我看不出它是如何工作的

ORDER BY order_by_expression
[ COLLATE collation_name ] 
[ ASC | DESC ] 
[ ,...n ] 
[ <offset_fetch> ]


<offset_fetch> ::=
{ 
    OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
    [
      FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
    ]
}