ROW_NUMBER()在SQL中没有OVER - 两种方法

时间:2016-07-01 17:48:32

标签: sql sql-server

为什么以下代码会在我的情况下产生不同的结果:

select 
 ROW_NUMBER() OVER (order by (select 1)) AS RowNumber_approach1
,ROW_NUMBER() OVER (order by %%physloc%%) AS RowNumber_approach2
from dbo.tb

参考(有更多方法): http://blog.sqlauthority.com/2015/05/05/sql-server-generating-row-number-without-ordering-any-columns/

虽然听起来像是愚蠢的: ROW_NUMBER() without over in SQL 但是这个问题没有指出两种方法之间的区别。它都没有提供答案。

更新以下评论。我想解释一下我想要实现的目标。我加载了一个文件:

Bulk insert [dbo].[temp]
from 'C:\sql\CSV\MyFile.csv' 
with ( 
    fieldterminator =';'
    ,rowterminator='\n'
    ,FIRSTROW=2
    ,CODEPAGE ='ACP')

现在我想查看原始订单(与文件中的相同)。没有事先修改文件是否可能?

3 个答案:

答案 0 :(得分:1)

%%physloc%%是一个未记录的列,它返回记录的物理位置。

按此顺序排序可能(但不总是)产生返回记录的顺序结果,而不指定ORDER BY。因此,当您在ROW_NUMBER()订单上使用%%physloc%%时,它似乎是顺序的。

但是,按SELECT 1排序会在结果集中随机分配ROW_NUMBER()值。

如果你真的不在乎分配给哪条记录的价值,两者都没问题。但要记住的一件事是,按%%physloc%%排序实际上会对这些值进行排序,以确定ROW_NUMBER()结果的正确位置。

SELECT 1排序不会。

答案 1 :(得分:1)

@MartinSmith是正确的,除非您只是尝试添加任意序列号都没有多大用处。虽然我可以想到几个原因,但我会添加一个任意数字,包括:

  • 使用cte ......
  • 删除重复的条目
  • 将假身份列添加到我正在SELECT INTO创建的临时表中(是的,我知道这可能不是最佳做法,但这将是一次性分析而非生产查询)。

无论如何,我不认为保证总能得到相同的结果,但如果查询中存在NO ORDER BY语句,则应该多次。因为%% physloc %%将按物理位置标识符(文件位置,页面和插槽)http://sqlity.net/en/2451/physloc/的顺序返回记录。索引,主键,联接和许多其他内容将改变SQL服务器优化,因此可能会改变结果的顺序。

性能方面,您应该使用SELECT 1/ no OVER statement获得收益,因为您的查询不会依赖于更多数据。

答案 2 :(得分:1)

未记录的%%physloc%%包含三个标识符:fileidpageidslotid

此位置是实际地址。当SQL Server读取表时,通常会在"页面顺序"中读取表。 - 第一页,然后是第二页,依此类推。实际上,您在询问是否保证读取顺序在物理地址方面有所增加。

没有理由认为"页面顺序"将与物理位置相同。不可否认,这通常是正确的。例如,我希望这两个值对于:

是相同的
  • 适合在仅包含一个文件的文件组上定义的一个页面中的表。
  • 在只有一个文件的文件组上定义的静态系统(我认为SQL Server将按顺序分配新页面)上一次创建的表。

但是,中间处理可能导致无序页面,因此可以从文件组中的多个文件中分配页面。你看到了类似的结果。

话虽如此,order by %%physloc%%order by (select null)之间存在重大差异(我是怎么写的)。在第一种情况下,SQL Server将对订单进行排序。第二个(根据经验但不是文档)阻止实际排序。