是否可以保证SELECT ROW_NUMBER()返回按生成的行号排序的结果?


10

例如考虑SQL查询:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC)
FROM
   [FooTable] AS A

在这里,我观察到返回的结果按A. [名称]排序。如果我将ROW_NUMBER函数中定义的排序列更改为另一列,那么结果将再次由该列进行排序。

我期望将行号分配给这些行,但是我不希望这些行以相同的标准返回排序。这仅仅是查询执行方式的副作用(就我而言,在SQL Server 2008 R2上)还是可以保证这种行为?(我找不到关于这种保证的参考)。


10
从来没有任何保证。曾经 除非您告诉SQL Server如何订购某些东西,否则可以随意以任意顺序返回数据。通过省略顺序,您是在告诉SQL Server您不在乎该顺序。如果您想要保证,只需输入ORDER BY子句即可。
亚伦·伯特兰

有一个很好的理由要问,因为有问题的order-by子句非常复杂,因此复制既会造成代码维护混乱,又会增加将来出现缺陷的可能性。另一个选择是较小的重构,我认为如果SQL标准定义了隐式排序顺序,我也许可以避免。无论如何,我只是想知道是否有涉及这一点的正式文档。
redcalx 2012年

1
那为什么不问这个问题呢?
亚伦·伯特兰

Answers:


14

如果您提出了这个问题,我想您实际上是想问:

如何在ROW_NUMBER()不重复复杂ORDER BY表达式的情况下排序?

我们本可以告诉您为ROW_NUMBER()表达式创建一个别名,然后使用别名进行排序:

SELECT
   A.[Name],
   rn = ROW_NUMBER() OVER (ORDER BY <complex expression>)
FROM
   dbo.[FooTable] AS A
ORDER BY rn;

现在,您只需要在一个位置上更改表达式,结果排序将基于该表达式而无需重复。


6
实际上,repeating the complex ORDER BY expression甚至不能保证输出将按ROW_NUMBER()顺序输出。除非ORDER BY子句中的列形成唯一键。
孔夫子2012年

22

绝对不。证明:

SELECT
   A.[Name],
   ROW_NUMBER() OVER(ORDER BY A.[Name] ASC),
   ROW_NUMBER() OVER(ORDER BY A.[Name] DESC)
FROM
   [FooTable] AS A

确保SQL中的顺序的唯一方法是要求它,将 ORDER BY其用于结果本身。


好的,我再添加一个限定条件-如果仅指定一个ROW_NUMBER()子句,则可以保证对结果进行排序。
redcalx 2012年

22
保证SQL中的顺序的唯一方法是要求它
Remus Rusanu 2012年

0

实际上,(老)问题可以扩展到也包括通过分区部分,似乎有一个隐含的顺序,首先将通过分区,然后按顺序部(S)

因此,这并不像某些人所建议的那样简单,就是要分配row_number并将其用于排序。

我们还需要一个嵌套的sql来提取partition by子句(当然,如果我们不想简单地重复它)

根据经验,我们似乎隐式地获得了最后一行排序

Select
  <field-list>, 
  rn=Row_Number() over(partition by <PartionClause>) order by <OrderClause>
from ....
Order by <PartionClause> asc, rn asc

但是我们缺乏的是任何证据或保证它永远存在。

(如果正在播放多个Row_Number()调用,则似乎是最后一个发出排序的调用)

还请注意,如果您执行计划显式添加订单,则清楚地显示了最终的排序步骤,对已排序的集合进行排序是最坏的情况,因此使用Order By花费的时间要比不使用Set By花费的时间长得多


1
这并不能真正回答问题,似乎既不同意已接受的答案,也不太赞成。
埃里克·达令

我同意我的评论不是答案。好吧,公认的答案并不是真正的答案,只是它说我们最好不要相信订单,这就是问题所在。从执行计划可以看出,它实际上是在进行排序,如果添加显式顺序,则将获得第二种排序。但这不是证明,而是经验知识的一部分
Eske Rahn

(当然,只有在没有合适的索引可用于访问表时,它才会进行排序,而只是添加它以表明明确给出订单通常不是免费的)
Eske Rahn
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.