SQL Server 2008的分页方法?
我必须处理可能很大的记录列表,并且我一直在谷歌搜索避免选择整个列表的方法,相反,我想让用户选择一个页面(例如从 1 到 10)并相应地显示记录。
比如说,对于 1000 条记录,我将有 100 个页面,每页 10 条记录,并且将首先显示最近的 10 条记录,然后如果用户单击第 5 页,它将显示从 41 到 50 的记录。
添加每条记录的行号然后根据行号查询?有没有更好的方法来实现分页结果而不需要太多开销? 到目前为止,此处描述的这些方法看起来最有前途:
http://developer.berlios。 de/docman/display_doc.php?docid=739&group_id=2899
I have to work with a potentially large list of records and I've been Googling for ways to avoid selecting the whole list, instead I want to let users select a page (like from 1 to 10) and display the records accordingly.
Say, for 1000 records I will have 100 pages of 10 records each and the most recent 10 records will be displayed first then if the user click on page 5, it will show records from 41 to 50.
Is it a good idea to add a row number to each record then query based on row number? Is there a better way of achieving the paging result without too much overhead?
So far those methods as described here look the most promising:
http://developer.berlios.de/docman/display_doc.php?docid=739&group_id=2899
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
以下 T-SQL 存储过程是非常高效的分页实现。 SQL优化器可以非常快地找到第一个ID。将此与 ROWCOUNT 的使用结合起来,您将获得一种既具有 CPU 效率又具有读取效率的方法。对于具有大量行的表,它肯定胜过我见过的使用临时表或表变量的任何方法。
注意:我在本例中使用了顺序标识列,但代码适用于任何适合页面排序的列。此外,所使用的列中的序列中断不会影响结果,因为代码选择了许多行而不是列值。
编辑:如果您要对具有潜在非唯一值(例如 LastName)的列进行排序,则将第二列添加到 Order By 子句以使排序值再次唯一。
The following T-SQL stored procedure is a very efficient implementation of paging. THE SQL optimiser can find the first ID very fast. Combine this with the use of ROWCOUNT, and you have an approach that is both CPU-efficient and read-efficient. For a table with a large number of rows, it certainly beats any approach that I've seen using a temporary table or table variable.
NB: I'm using a sequential identity column in this example, but the code works on any column suitable for page sorting. Also, sequence breaks in the column being used don't affect the result as the code selects a number of rows rather than a column value.
EDIT: If you're sorting on a column with potentially non-unique values (eg LastName), then add a second column to the Order By clause to make the sort values unique again.
如果您使用具有两个 row_number() 列的 CTE - 一列按升序排序,一列降序排序,则通过添加两列 row_number 即可获得用于分页的行号以及总记录。
If you use a CTE with two row_number() columns - one sorted asc, one desc, you get row numbers for paging as well as the total records by adding the two row_number columns.
使用OFFSET
其他人已经解释了如何使用
ROW_NUMBER() OVER()
排名函数来执行页面。值得一提的是,SQL Server 2012终于包含了对SQL标准的支持OFFSET .. FETCH
子句:如果您使用的是 SQL Server 2012 并且向后兼容性不是问题,您可能应该更喜欢此子句,因为在特殊情况下 SQL Server 可以更优化地执行它。
使用 SEEK 方法
有一种完全不同、更快的方法可以在 SQL 中执行分页。这通常称为“查找方法”,如 此博客文章位于此处。
@previousScore
和@previousPlayerId
值是上一页最后一条记录的相应值。这允许您获取“下一页”。如果ORDER BY
方向是ASC
,则只需使用>
即可。使用上述方法,如果没有先获取前 40 条记录,则无法立即跳转到第 4 页。但通常情况下,您无论如何都不想跳那么远。相反,您可以获得更快的查询,可能能够在恒定时间内获取数据,具体取决于您的索引。另外,无论基础数据是否发生变化,您的页面都保持“稳定”(例如,在第 1 页上,而在第 4 页上)。
例如,当在 Web 应用程序中延迟加载更多数据时,这是实现分页的最佳方法。
请注意,“seek 方法”也称为键集分页。
Using OFFSET
Others have explained how the
ROW_NUMBER() OVER()
ranking function can be used to perform pages. It's worth mentioning that SQL Server 2012 finally included support for the SQL standardOFFSET .. FETCH
clause:If you're using SQL Server 2012 and backwards-compatibility is not an issue, you should probably prefer this clause as it will be executed more optimally by SQL Server in corner cases.
Using the SEEK Method
There is an entirely different, much faster way to perform paging in SQL. This is often called the "seek method" as described in this blog post here.
The
@previousScore
and@previousPlayerId
values are the respective values of the last record from the previous page. This allows you to fetch the "next" page. If theORDER BY
direction isASC
, simply use>
instead.With the above method, you cannot immediately jump to page 4 without having first fetched the previous 40 records. But often, you do not want to jump that far anyway. Instead, you get a much faster query that might be able to fetch data in constant time, depending on your indexing. Plus, your pages remain "stable", no matter if the underlying data changes (e.g. on page 1, while you're on page 4).
This is the best way to implement paging when lazy loading more data in web applications, for instance.
Note, the "seek method" is also called keyset paging.
尝试这样的事情:
Try something like this:
这是 @RoadWarrior 代码的更新版本,使用 TOP。性能相同,而且速度极快。确保您在 TestTable.ID 上有索引
Here's an updated version of @RoadWarrior's code, using TOP. Performance is identical, and extremely fast. Make sure you have an index on TestTable.ID
试试这个
Try this
为什么不使用推荐的
Why not to use recommended solution: