我必须在现有查询中添加行号,以便我可以跟踪已添加到 Redis 中的数据量。如果我的查询失败,那么我可以从其他表中更新的该行开始。
查询从表中 1000 行后开始获取数据
SELECT * FROM (SELECT *, ROW_NUMBER() OVER (Order by (select 1)) as rn ) as X where rn > 1000
查询工作正常。如果有什么方法可以让我在不使用 order by 的情况下获得行号。
这里的
select 1
是什么?
查询是否经过优化,或者我可以通过其他方式来完成。请提供更好的解决方案。
无需担心在
ORDER BY
表达式中指定常量。以下内容摘自Itzik Ben-Gan
撰写的Microsoft SQL Server 2012 High-Performance T-SQL Using Window Functions(可从Microsoft免费电子书网站免费下载):
如前所述,窗口顺序子句是强制性的,并且 SQL Server 不允许基于常量进行排序,例如, 按 NULL 排序。但令人惊讶的是,当传递基于 返回常量的子查询 — 例如,ORDER BY (SELECT NULL)—SQL Server 将接受它。同时,优化器 取消嵌套或扩展表达式并意识到排序是 所有行都相同。因此,它消除了订购要求 从输入数据。这是一个完整的查询来证明这一点 技术:
SELECT actid, tranid, val,
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM dbo.Transactions;
在 Index Scan 迭代器的属性中观察 Ordered 属性为 False,意味着迭代器不需要返回 按索引键顺序排列的数据
上面的意思是,当您使用常量排序时,不会执行。我强烈建议阅读这本书,因为
Itzik Ben-Gan
深入描述了窗口函数如何工作以及如何在使用它们时优化各种情况。
您可以使用任何文字值,例如:
order by (select 0)
order by (select null)
order by (select 'test')
尝试
order by 1
。阅读错误消息。然后恢复order by (select 1)
。请意识到,无论是谁编写此代码,都曾在某个时候阅读过错误消息,然后决定正确的做法是欺骗系统不引发错误,而不是意识到错误试图提醒他们注意的基本事实。
表格没有固有的顺序。如果您想要某种可以依赖的排序形式,则需要为任何
ORDER BY
子句提供足够的确定性表达式,以便每一行都被唯一标识和排序。
任何其他事情,包括欺骗系统不发出错误,都是希望系统会做一些明智的事情,而不使用提供给您的工具来确保它做一些明智的事情 - 一个明确指定的
ORDER BY
子句。
这里的 select 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())