使用row_number()时可以依赖输出顺序吗?

时间:2009-07-10 16:42:08

标签: sql sql-server tsql

我相信答案是没有。我正在寻找一个反例来表明输出顺序无法保证,没有一个order by子句。

考虑:

create table #order (orderId int primary key clustered
    , customerId int not null -- references customer(customerId)
    , orderDateTIme datetime not null)

insert into #order values (1, 100, '2009-01-01')
insert into #order values (2, 101, '2009-01-02')
insert into #order values (3, 102, '2009-01-03')
insert into #order values (4, 103, '2009-01-04')
insert into #order values (5, 100, '2009-01-05')
insert into #order values (6, 101, '2009-01-06')
insert into #order values (7, 101, '2009-01-07')
insert into #order values (8, 103, '2009-01-08')
insert into #order values (9, 105, '2009-01-09')
insert into #order values (10, 100, '2009-01-10')
insert into #order values (11, 101, '2009-01-11')
insert into #order values (12, 102, '2009-01-12')
insert into #order values (13, 103, '2009-01-13')
insert into #order values (14, 100, '2009-01-14')
insert into #order values (15, 100, '2009-01-15')
insert into #order values (16, 101, '2009-01-16')
insert into #order values (17, 102, '2009-01-17')
insert into #order values (18, 101, '2009-01-18')
insert into #order values (19, 100, '2009-01-19')
insert into #order values (20, 101, '2009-01-20')

select * from #order
-- Results in PK order due to clustered primary key

select orderId, CustomerId, orderDateTime
    , row_number() over (partition by customerId order by orderDateTime) RN
from #order

在MS SQL Server 2005上,输出排序有两个属性:

  1. 每个customerId的行都是 在输出中连续。

  2. Row_number()是连续的     每个customerId。

  3. 我的理解是,如果没有明确的order by子句,则不保证这两个属性。我正在寻找一个示例,其中上述属性不是由order by子句强制执行,但只是MS SQL Server如何工作的结果。如果需要,请随意在您的示例中开发自己的表定义,索引等。

    或者,如果我错了,即使没有明确的order by子句,也会提供指向这些排序的参考链接。

4 个答案:

答案 0 :(得分:10)

如果您想要一个有序的结果集,在SELECT 中添加一个ORDER BY子句。期。其他任何东西都是间接的,可能会也可能不会起作用,这取决于您正在测试的当前SQL构建,优化器的当天情绪以及双鱼座的火星传输阶段。

一个与你的假设相矛盾的微不足道的例子:

select orderId, CustomerId, orderDateTime
    , row_number() over (partition by customerId order by orderDateTime) RN
    , row_number() over (partition by orderDateTime order by customerId) AntiRN
from #order

答案 1 :(得分:2)

我努力在这里找到相关性;如果你想要显式排序,推荐的方法是在查询中使用ORDER BY子句。

在生成依赖于结果顺序的查询时,我从不依赖于表的默认排序。任何现代的RDBMS都能够根据索引等优化订单,因此不必担心。

关于row_number,虽然副作用是如果不存在ORDER BY子句,则输出按ROW_NUMBER值排序,不能依赖于此行为,因为它不能保证

同样,保证输出顺序的唯一方式是使用ORDER BY子句。

答案 2 :(得分:1)

如上所述,如果没有ORDER BY,则不能依赖行顺序。

但是,您可以依赖ROW_NUMBER()函数

SELECT
    principal_id, name, 
    ROW_NUMBER() OVER (ORDER BY principal_id DESC) AS DemoRank
FROM
    msdb.sys.database_principals
ORDER BY
    name

如果您通过DemoRank使用客户端中的数据,那么即使没有ORDER BY子句也没问题

如果你依赖于记录集排序(序数索引),那么没有。

上面的例子给出了第一行(index = 0)为'##MS_PolicyEventProcessingLogin##',但是使用DemoRank值给出了“db_denydatawriter”

基本上,使用ORDER BY。

答案 3 :(得分:0)

如果您想订购,必须使用ORDER BY。

只需用

查看执行计划
SET SHOWPLAN_ALL ON

如果StmtText列中没有“order by”,那么只需在完成所有工作后对它们进行排序即可。有时你很幸运,有时候没有,数据如何存储/加载/过滤/加入等等以及如何返回。