没有ORDER BY的ROW_NUMBER

时间:2017-05-22 06:07:02

标签: sql sql-server tsql window-functions

我已在现有查询中添加行号,以便跟踪已向Redis添加的数据量。如果我的查询失败,那么我可以从该行开始,而不是在其他表中更新。

查询以从表

开始1000行之后开始数据
SELECT * FROM (SELECT *, ROW_NUMBER() OVER (Order by (select 1)) as rn ) as X where rn > 1000

查询工作正常。如果有任何方法,我可以在不使用订单的情况下获得行。

这里select 1是什么?

查询是否已优化,或者我可以通过其他方式执行此操作。请提供更好的解决方案。

4 个答案:

答案 0 :(得分:33)

无需担心在ORDER BY表达式中指定常量。以下内容引自Itzik Ben-Gan撰写的Microsoft SQL Server 2012 High-Performance T-SQL Using Window Functions(可从Microsoft免费电子书网站免费下载):

  

如前所述,窗口顺序子句是必需的,而SQL Server   不允许排序基于常量 - 例如,   ORDER BY NULL。但令人惊讶的是,当传递基于a的表达式时   返回常量的子查询 - 例如,ORDER BY(SELECT   NULL)-SQL Server将接受它。同时,优化器   解开或扩展表达式并实现排序   所有行都一样。因此,它删除了订购要求   来自输入数据。这是一个完整的查询,展示了这一点   技术:

SELECT actid, tranid, val,
 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM dbo.Transactions;

enter image description here

  

在索引扫描迭代器的属性中观察Ordered   property为False,表示迭代器不需要返回   索引键顺序中的数据

以上意味着不使用常量排序时。我强烈建议您阅读本书,Itzik Ben-Gan深入介绍了窗口函数的工作原理以及如何在使用它们时优化各种情况。

答案 1 :(得分:6)

尝试order by 1。阅读错误消息。然后恢复order by (select 1)。意识到写这篇文章的人在某些时候已经阅读了错误信息,然后决定正确的做法是欺骗系统不引发错误,而不是意识到错误试图提醒他们的基本事实。

表没有固有的顺序。如果您想要某种可以依赖的排序形式,那么您可以为任何ORDER BY子句提供足够的确定性表达式,以便每行都被唯一标识和排序。

其他任何事情,包括欺骗系统不会发出错误,希望系统会做一些合理的事情,而不使用提供给你的工具来确保它确实一些明智的东西 - 一个明确指定的ORDER BY条款。

答案 2 :(得分:4)

您可以使用任何文字值

order by (select 0)

order by (select null)

order by (select 'test')

有关详细信息,请参阅此处 https://exploresql.com/2017/03/31/row_number-function-with-no-specific-order/

答案 3 :(得分:0)

这里的选择1是什么?

在这种情况下,查询的作者实际上并没有考虑任何特定的排序。 ROW_NUMBER需要ORDER BY clause,因此提供它是满足解析器的一种方式。

按“常数”排序将创建“不确定”顺序(查询优化器可以选择合适的任何顺序)。

最简单的思考方式是:

ROW_NUMBER() OVER(ORDER BY 1)    -- error
ROW_NUMBER() OVER(ORDER BY NULL) -- error

几乎没有可能为“技巧”查询优化器提供常量表达的方案:

ROW_NUMBER() OVER(ORDER BY (SELECT 1)) -- already presented

其他选项:

ROW_NUMBER() OVER(ORDER BY 1/0)       -- should not be used
ROW_NUMBER() OVER(ORDER BY @@SPID)
ROW_NUMBER() OVER(ORDER BY DB_ID())
ROW_NUMBER() OVER(ORDER BY USER_ID())

db<>fiddle demo