以  项目表 PM_Project  为例。

  PM_Project 全部内容如下(共6条数据):

一、Top – Not In - Top 方式分页

直接的,原始的,不采用函数,纯手动挡。

分步探索过程:

  采用的最直接做法就是使用两个Top来实现。

DECLARE  @pageSize INT =4,@pageIndex INT =1
BEGIN
SELECT TOP (@pageSize)
*
FROM ( SELECT TOP (@pageSize * @pageIndex)
*
FROM PM_Project
ORDER BY Id DESC --- 内查询倒序
) AS temp
ORDER BY Id ---外查询正序, 内外查询顺序不一致即可
END
GO

结果:

乍一看是没有问题的,但是仔细一看会发现其中存在的问题。当符合条件的纪录集小于每页记录数时,没有问题,但是当大于就有问题了。

例如上边代码,实际满足条件的是6条,即全部满足(因为根本就没加条件)。第一页是没有问题的,但是第二页就有问题了。现在共6条数据,每页4条,按理说第二页应该只有2条。但是使用如上的方法,每次都会返回4条记录。

当pageIndex =2 时,结果如下:

沿用上面的思路,把代码修改为了采用三层查询,最内一层查询所有满足条件的数据,然后第二层选择Top PageSize个所有NOT IN 第一层数据中的数据即可,因为使用了NOT IN所以不存在第一种方法中的bug

DECLARE  @pageSize INT =4,@pageIndex INT =2  ---直接看第二页
BEGIN SELECT *
FROM PM_Project
WHERE Id IN (
SELECT TOP ( @pageSize )
Id
FROM PM_Project
WHERE Id NOT IN ( SELECT TOP ( @pageSize * (@pageIndex-1) )---去除本页之前的所有id
Id
FROM PM_Project
ORDER BY Id)
ORDER BY PM_Project.Id)
ORDER BY PM_Project.Id ASC END
GO

结果:

二、ROW_NUMBER()的方式实现分页

语法:  

ROW_NUMBER ( ) OVER ( [ PARTITION BY value_expression , ... [ n ] ] order_by_clause )

分步过程:

首先查询全部满足条件的数据,并使用 ROW_NUMBER() 函数,可以根据给定好的排序字段规则,为查询结果生成记录序号。

SELECT ROW_NUMBER() OVER (ORDER BY id) rownum,
    *
FROM PM_Project

结果:(共6条数据)

然后用TOP()函数取出一页数据

DECLARE  @pageSize INT =4,@pageIndex INT =1  ------每页4条,第一页
BEGIN SELECT TOP(@pageSize*@pageIndex)
ROW_NUMBER() OVER (ORDER BY id) rownum,
*
FROM PM_Project
END
GO

这样取第一页还是可以的,但是往后就会越来越多。现在将上边的查询作为内查询,再外查询中通过条件来控制获取页数问题。

策略很简单,首先我们选取包含要查页的数据,然后使用ROW_NUMER函数进行编号, 然后在外查询中指定rownum大于页起始记录即可。这种方式简单快捷。

DECLARE  @pageSize INT =4,@pageIndex INT =2  ------每页4条,第二页
BEGIN
SELECT*FROM
(
SELECT TOP(@pageSize*@pageIndex)
ROW_NUMBER() OVER (ORDER BY id) rownum,*
FROM PM_Project
)temp
WHERE temp.rownum>(@pageSize*(@pageIndex-1))
END
GO

查询第二页的结果:

在 Sql Server 2000 之后的版本中,ROW_NUMBER() 这种分页方式一直都是很不错的,比起之前的游标分页,性能好了很多,因为 ROW_NUMBER() 并不会引起全表扫表,但是,语法比较复杂,并且,随着页码的增加,性能也越来越差。

三、使用CTE(common_table_expression,公用表表达式)的方式

使用很简单,就是把内查询放在CTE 里面。

DECLARE  @pageSize INT =4,@pageIndex INT =2
BEGIN
WITH temp
AS ( SELECT TOP ( @pageSize * @pageIndex )
ROW_NUMBER() OVER ( ORDER BY id) AS rownum ,
*
FROM PM_Project
)
SELECT *
FROM temp
WHERE temp.rownum > ( @pageSize * ( @pageIndex - 1 ) )
ORDER BY temp.Id
END
GO

结果:

四、使用 OFFSET  FETCH 子句分页

语法:

OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }

FETCH { FIRST | NEXT } { integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY

从语法可以看出来 两个方法 后面不但能接 intege 类型的参数,还能接 表达式的,比如  1*2 +3 之类的,同时, Row 或者 Rows 是不区分大小写和单复数的。

SQL Server 2012及以后版本支持。

例句:

DECLARE  @pageSize INT =4,@pageIndex INT =2
BEGIN SELECT*FROM PM_Project
ORDER BY Id
OFFSET ( @pageSize * ( @pageIndex - 1 )) ROWS
FETCH NEXT @pageSize ROWS ONLY END
GO

结果:

性能对比:

  在 Sql Server 2012 里面,分页方法中,Offset and Fetch 同 ROW_NUMBER() 比较起来,无论是性能还是语法,都是有优势的。
  但是性能方面,优势并不是太大,两者 的 IO 消耗完全相同。
  只是 在 CPU 方面,Offset and Fetch 方面要好一些,但是不明显。
  如果对于一个 每秒都要处理成千上万条的分页Sql语句的DB 来说,Offset and Fetch 在CPU 方面的优势会比较明显的,否则,性能的提升并不明显。

SQLServer数据库分页的更多相关文章

  1. Sqlserver数据库分页查询

    Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID.YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询 ...

  2. MySQL、SqlServer、Oracle三大主流数据库分页查询

    在这里主要讲解一下MySQL.SQLServer2000(及SQLServer2005)和ORCALE三种数据库实现分页查询的方法.可能会有人说这些网上都有,但我的主要目的是把这些知识通过我实际的应用 ...

  3. 【转载】Sqlserver数据库中无自增Id的情况下使用ROW_NUMBER()函数进行数据分页

    在Sqlserver数据库中,如果查询表中含有自增长Id列,一般会采用select Top的方式来数据的分页操作.而实际上很多数据表设计的时候,不一定含有自增长Id列,那么数据库没有Id自增列的时候要 ...

  4. mysql / sqlserver / oracle 常见数据库分页

    空闲时间里用着mysql学习开发测试平台和测试用具, 在公司里将可用的测试平台部署,将数据库换成sqlserver 巴望着能去用oracle的公司 mysql中的分页 limit是mysql的语法se ...

  5. MySQL、SqlServer、Oracle三大主流数据库分页查询 (MySQL分页不能用top,因为不支持)

    一. MySQL 数据库 分页查询MySQL数据库实现分页比较简单,提供了 LIMIT函数.一般只需要直接写到sql语句后面就行了.LIMIT子 句可以用来限制由SELECT语句返回过来的数据数量,它 ...

  6. 浅谈SQL Server数据库分页

    数据库分页是老生常谈的问题了.如果使用ORM框架,再使用LINQ的话,一个Skip和Take就可以搞定.但是有时由于限制,需要使用存储过程来实现.在SQLServer中使用存储过程实现分页的已经有很多 ...

  7. sqlserver 存储过程分页管理

    -- =============================================-- Author:  <Author:刘畅>-- Create date: <Cre ...

  8. Oracle、MySql、SQLServer数据分页查询

    看过此博文后Oracle.MySql.SQLServer 数据分页查询,在根据公司的RegionRes表格做出了 SQLserver的分页查询语句: 别名.字段 FROM( SELECT row_nu ...

  9. SQL多表连接查询以及mysql数据库、sqlserver数据库常见不同点

    mysql数据库表及数据准备语句: USE test; DROP TABLE IF EXISTS `teacher_table`; DROP TABLE IF EXISTS `student_tabl ...

随机推荐

  1. Unity基础(5) Shadow Map 概述

    这篇是自己看shadow map是的一些笔记,内容稍稍凌乱,如有错误请帮忙纠正 1.常见阴影处理方式 Shadow Map : using Z-Buffer Shadow Mapping 的原理与实践 ...

  2. js模块化规范—CMD规范

    CMD规范说明 专门用于浏览器端, 模块的加载是异步的 ,模块使用时才会加载执行,github地址 CMD基本语法 定义暴露模块 //定义有依赖的模块 define(function(require, ...

  3. vue获取当前元素

    Html: <li><a href="#" v-on:click="typeStyle">萨克斯萨克<span></s ...

  4. iptables nat 技术转发

    NAT 一. 什么是 NAT NAT(Network Address Translation)译为网络地址转换.通常路由器在转发我们的数据包时,仅仅会将源MAC地址换成自己的MAC地址,但是NAT技术 ...

  5. php面试中的经典问题

    原文:https://blog.csdn.net/ghostlv/article/details/51284745 问题一问题描述考虑下面代码: $str1 = 'yabadabadoo';$str2 ...

  6. 【js】项目中遇到的零星知识点

    1.将进行url编码的json字符串转成json对象 在解析为json对象之前,要先用decodeURIComponent(str)来进行解码,然后这json串又变成了我们原先的json串了.然后我们 ...

  7. ElasticSearch(站内搜索) 转发 https://www.cnblogs.com/xibei666/p/5929970.html

    简介 Elasticsearch是一个实时的分布式搜索和分析引擎.它可以帮助你用前所未有的速度去处理大规模数据.它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者进行组合.Elasticse ...

  8. MemCache在.NET中使用Memcached.ClientLibrary详解 转发 https://www.cnblogs.com/li150dan/p/9529112.html

    本文说明:memcached分布式缓存的负载均衡配置比例,数据压缩,socket的详细配置等,以及在.net中的常用方法 首先下载客户端的3个dll,ICSharpCode.SharpZipLib.d ...

  9. docker 14 dockerfile自定义mycentos

    Base镜像(scratch) Docker Hub中99%的镜像是通过在base镜像中安装和配置需要的软件构建出来的.也就是说base镜像是所有其他镜像的鼻祖. hub默认centos镜像是什么情况 ...

  10. Linux 内核协议栈 学习资料

    终极资料 1.<Understanding Linux Network Internals> 2.<TCP/IP Architecture, Design and Implement ...