ROW_NUMBER()总是会命令外部结果吗?

时间:2017-03-29 17:27:57

标签: sql-server common-table-expression

我正在使用CTE根据销售排名对书籍作者进行排名。我了解ROW_NUMBER()可以使用ORDER BY来确定基于它的返回行号。

我的查询如下:

WITH cte (idWork, author, rn)
AS
(
    SELECT
        idWork,
        authorName,
        ROW_NUMBER() OVER (PARTITION BY idWork ORDER BY authorSalesRank)
    FROM dbo.Works_Authors_Works
    INNER JOIN Authors ON Authors.idAuthor = Works_Authors_Works.idAuthor
)
SELECT TOP 100 * FROM cte 

我注意到结果看起来像这样,这是预期的:

+---------+----------------+------+
| idWork  | author         | rn   |
+---------+----------------+------+
| 1       | test1          | 1    |
| 1       | test2          | 2    |
| 1       | test3          | 3    |
| 2       | beep1          | 1    |
| 2       | beep2          | 2    |
| 3       | nobody         | 1    |
+---------+----------------+------+

我对此CTE有两个问题:

  • 结果是否始终在ROW_NUMBER字段rn上排序?就像结果在idWork上分组然后在rn上排序一样?例如,当idWork为1时,行在rn上从1,2,然后3排序。这是巧合还是总是这样?
  • 如果我执行SELECT TOP 1 * FROM cte WHERE idWork = 1,它是否会始终返回rn = 1的行?

在执行计划中,它有一个输入排序idWorkauthorSalesRank。这些暗示外部结果也是这样排序的吗?

execution plan execution plan - sort details

1 个答案:

答案 0 :(得分:3)

您应该明确订购它。

WITH cte (idWork, author, rn) AS (
    SELECT
        idWork,
        authorName,
        ROW_NUMBER() OVER (PARTITION BY idWork ORDER BY authorSalesRank) AS rn
    FROM dbo.Works_Authors_Works
    INNER JOIN Authors ON Authors.idAuthor = Works_Authors_Works.idAuthor
)
SELECT TOP 100 *
FROM cte
order by idWork, rn

如果没有指定订单,SQL(所有数据库)都不保证订单,即使似乎喜欢它“总是有效”,你也不应该依赖那个轶事证据。