如何在SQL Server查询中实现高效分页

数据库 SQL Server
经常写SQL查询脚本的朋友,很可能会遭遇分页查询的问题。在MSSQL2000及以前的版本中,分页的写法大多采用纯Top嵌套方式,写法比较复杂、而且效率并不理想。今天我们就谈谈ROW_NUMBER和offset的语法和在分页中的应用。

 经常写SQL查询脚本的朋友,很可能会遭遇分页查询的问题。在MSSQL2000及以前的版本中,分页的写法大多采用纯Top嵌套方式,写法比较复杂、而且效率并不理想。

从MSSQL2005开始,SQL Server提供了一个内置函数ROW_NUMBER,这是一个非常神奇的函数。

从MSSQL2012开始,SQL Server提供了offset方法进行分页。使用offset startPage rows fetch next pageSize rows only 方式进行分页。

今天我们就谈谈ROW_NUMBER和offset的语法和在分页中的应用。

[[253435]]
ROW_NUMBER的含义及语法定义

ROW_NUMBER实现对结果集的输出进行编号。 具体来说,返回结果集分区内行的序列号,每个分区的***行从 1 开始。

ROW_NUMBER ( ) OVER ( [ PARTITION BY 字段 , ] order_by_clause )PARTITION BY:将 FROM 子句生成的结果集划分为应用 ROW_NUMBER 函数的分区。 value_expression 指定对结果集进行分区所依据的列。 如果未指定 PARTITION BY,则此函数将查询结果集的所有行视为单个组。order_by_clause: 子句可确定在特定分区中为行分配*** ROW_NUMBER 的顺序。 order by 子句是必选项。返回值:bigint。结果集分区内行的序列号。offset的含义及语法定义

offset是order by的子句,主要用来限定返回的行数,用来做分页也是很合适的。只是从MSSQL2012才开始支持。语法结构如下:

  1. FETCH { NEXT } { integer_constant | fetch_row_count_expression } { ROWS } ONLY 

fetch_row_count_expression 可以是变量、参数或常量标量子查询。 在使用子查询时,它无法引用在外部查询范围中定义的任何列。也就是说,它无法与外部查询相关联。

结合到分页,语法语法: 

  1. offset startPage rows fetch next pageSize rows only 

其中起始页面:startPage=(@page-1)*@rows,页面大小:pageSize=@rows

演示数据准备

为了说明方便,我们准备一些演示数据,这是一个简单的业务销售表,字段只有业务员、销售区域和销售额,如下:

  1. declare @sale table( FName nvarchar(50), FDistrict nvarchar(50), FAmount decimal(28,10) ); 
  2. insert into @sale values ('张三','北京',20000), ('张三','上海',50000), ('张三','深圳',40000), ('张三','广州',30000), ('李四','北京',30000), ('李四','上海',50000), ('李四','深圳',40000), ('李四','广州',10000), ('王二','北京',70000), ('王二','上海',10000), ('王二','深圳',60000), ('王二','广州',20000), ('马六','北京',80000), ('马六','上海',20000), ('马六','深圳',70000), ('马六','广州',60000) 

准备演示数据

使用ROW_NUMBER分页

比如我们希望按照业务员+销售区域排序后,每4条记录一页显示,写法如下: 

  1. declare @pagesize int =4;--每页记录数  
  2. declare @pagenum int =1;--第几页  
  3. select v.* from (select row_number() over(order by FName,FDistrict) as FRowIndex,* from @sale) as v where v.FRowIndex between @pagesize*(@pagenum-1)+1 and @pagenum*@pagesize; 

分页查询

ROW_NUMBER函数在SQL中属于热名称(即刚定的名称FRowIndex),只可以出现在select子句中,需要放在子查询中。也可以先对子查询做好定义后面再直接引用,语法如下: 

  1. declare @pagesize int =4;--每页记录数  
  2. declare @pagenum int =1;--第几页  
  3. with saledata as ( select row_number() over(order by FName,FDistrict) as FRowIndex,* from @sale )  
  4. select * from saledata where FRowIndex between @pagesize*(@pagenum-1)+1 and @pagenum*@pagesize; 

分页查询

ROW_NUMBER来做分页查询,经过反复应用测试,效率还是很高的。完整的测试脚本参看下图:

使用OFFSET实现分页

重复的代码部分不再赘述,在查询时要注意,offset是Order By的子句,不能独立存在。语法结构如下: 

  1. select * from @sale order by FName,FDistrict offset (@pagenum-1)*@pagesize rows fetch next @pagesize rows only 

返回的结果与使用row_number是一致的。完整的测试脚本参看下图:

希望对您有所帮助! 

责任编辑:庞桂玉 来源: 快资讯
相关推荐

2011-08-19 09:30:42

分页查询SQL ServerMySQL

2024-03-05 15:28:38

SQL窗口函数分页查询

2010-09-13 13:19:16

Sql Server分

2010-05-07 09:58:27

SQL Server

2010-06-18 10:34:38

SQL Server

2010-11-10 15:23:55

SQL SERVER

2010-10-21 11:44:55

SQL Server分

2010-09-26 15:29:13

sql查询分页

2010-11-10 15:29:40

SQL SERVER

2010-09-07 10:35:38

SQL语句

2010-11-09 13:09:58

SQL Server分

2020-04-17 11:45:22

LibreOffice桌面应用

2009-07-15 15:18:01

JDBC连接SQL S

2020-11-19 15:26:36

SQLPandas代码

2010-10-21 10:28:13

SQL Server查

2011-06-27 14:50:41

SQL Server

2012-07-23 14:30:33

Oracle

2011-03-11 13:26:23

SQL Server数导入数据

2010-10-11 09:05:40

SQL Server

2020-08-17 14:56:02

PythonSQL
点赞
收藏

51CTO技术栈公众号