07. 分页写法小结
原文:07. 分页写法小结

分页的实现方式有这几种:
1. 在前台程序中,将所有的记录都读到本地,前台程序通过游标在数据集中上下移动,数据量大的话,性能很差,不推荐
2. 前台程序请求某一页数据时,到数据库做一次查询,返回符合条件的相应记录,这也是目前常用的方法
3. 对方式2的改进,当请求某一页时,同时将前后几页一并返回,用户翻页时就不需要反复请求数据库了。

对于2,3的实现,随着SQL Server版本的升级,常用的方法有三种:TOP,ROW_NUMBER,OFFSET/FETCH NEXT。
测试数据:

if OBJECT_ID('split_pages') is not null
drop table split_pages
GO
create table split_pages
(
ID int primary key,
Name varchar(100)
)
GO
declare @i int
set @i=1
while @i<=300
begin
insert into split_pages
select @i,'TEST' + CAST(@i as varchar(10))
set @i=@i+10
end
GO
select * from split_pages

一. TOP

SQL Server 2000时多用,另外,有人用过set rowcount来分页,原理类似TOP,不过需要反复设置set rowcount,不方便,而且set rowcount中的行数不能参与select语句的执行计划,只能起到控制行数的作用。
1. 哪种TOP写法更高效
(1) 利用order by正反排序

select *
from (select top 10 *
from (select top 20 * from split_pages order by ID) a
order by ID desc) b
order by ID

公式为:

declare @page_no int
declare @page_size intselect *
from (select top @page_size *
from (select top @page_size*@page_no * from split_pages order by ID) a
order by ID desc) b
order by ID

做完最里层select后,再对派生表查询时,index就没有效果了,而且越往后面要top更多的数据,这种写法会更慢。

(2) 利用NOT IN或者NOT EXISTS

select top 10 *
from split_pages
where ID NOT IN (select top 10 ID from split_pages order by ID)
order by ID

公式为:

declare @page_no int
declare @page_size intselect top @page_size *
from split_pages
where ID NOT IN (select top @page_size*(@page_no-1) ID from split_pages order by ID)
order by ID

通常在写SQL语句时,用IN/EXISTS不一样,如果逻辑不变的话, EXISTS的效率高。

不过,利用NOT IN分页,和用NOT EXISTS效果基本一样,因为都需要扫完全部数据。

(3) 利用ID大于MAX(ID)

select top 10 *
from split_pages
where ID > (select MAX(ID) from (select top 10 ID from split_pages order by ID) t)
order by ID

公式为:

declare @page_no int
declare @page_size intselect top @page_size *
from split_pages
where ID > (select MAX(ID) from (select top @page_size*(@page_no-1) ID from split_pages order by ID) t)
order by ID

在使用TOP分页时,这种用法效率最高。

2. SQL Server 2000与2005中TOP的区别
(1) SQL Server 2000时,top不支持变量,所以分页时,这些语句都要改成动态SQL
如下:

declare @page_no int
declare @page_size int
declare @sql varchar(8000)set @page_no = 2
set @page_size = 10
set @sql =
'select top ' + str(@page_size) + '*
from split_pages ' + '
where ID > (select MAX(ID) from (select top ' + str(@page_size*(@page_no-1))+ ' ID from split_pages order by ID) t)
order by ID'
exec(@sql)

(2) SQL Server 2005开始,top可以直接使用变量

如下:

declare @page_no int
declare @page_size int
set @page_no = 2
set @page_size = 10
select top (@page_size) *
from split_pages
where ID NOT IN (select top (@page_size*(@page_no-1)) ID from split_pages order by ID)
order by ID

二. ROW_NUMBER
SQL Server 2005开始的新语法,和ORACLE,DB2中的row_number()类似。性能比用TOP有所提升。

在利用ROW_NUMBER分页时,总页数/行数的计算,可以有这几种写法。
(1) 单独的SQL语句去获得总行数

select COUNT(*) AS TotRows
from split_pages
GO
declare @page_no int
declare @page_size intset @page_no = 2
set @page_size = 10;with tmp
AS
(
select *,
ROW_NUMBER() OVER(order by ID) num
from split_pages
)
select ID, Name
from tmp
where num BETWEEN (@page_size*(@page_no-1)+1) AND @page_size*@page_no
order by num

(2) 在ROW_NUMBER的同时用COUNT计算总行数

declare @page_no int
declare @page_size intset @page_no = 2
set @page_size = 10;WITH tmp
AS
(
select *,
ROW_NUMBER() OVER(order by ID) num,
COUNT(*) OVER() total
from split_pages
)
select ID, Name
from tmp
where num BETWEEN (@page_size*(@page_no-1)+1) AND @page_size*@page_no
order by num

(3) 仅使用ROW_NUMBER计算总行数,IO最少

declare @page_no int
declare @page_size intset @page_no = 2
set @page_size = 10;with tmp
as
(
select *,
ROW_NUMBER() OVER(order by ID) num,
ROW_NUMBER() OVER(order by ID desc) num_desc
from split_pages
)
select ID, Name, num_desc + num -1 as total
from tmp
where num BETWEEN (@page_size*(@page_no-1)+1) AND @page_size*@page_no
order by num

三. OFFSET/FETCH NEXT
SQL Server 2012的新语法,类似MYSQL,POSTGRESQL中的LIIMIT/OFFSET,据称性能比ROW_NUMBER又有了提升。

declare @page_no int
declare @page_size intset @page_no = 3
set @page_size = 10SELECT *,COUNT(*) OVER() AS Total
FROM split_pages
ORDER BY ID
OFFSET (@page -1) * @size ROWS
FETCH NEXT @size ROWS ONLY;

四. 其他方法
(1) 临时表
在SQL Server 2000时,利用临时表生成rownum来分页,不推荐。

select IDENTITY(int,1,1) as num,* into #t from split_pages
select * from #t where num between 11 and 20

(2) sp_cursoropen
利用游标,性能较差,原理类似在程序中把数据全部加载到本地,然后通过游标移动来分页。不作推荐。

posted on 2014-06-23 17:15 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/3804410.html

07. 分页写法小结相关推荐

  1. 04. 字符串合并与拆分写法小结

    04. 字符串合并与拆分写法小结 原文:04. 字符串合并与拆分写法小结 一. 字符合并 if OBJECT_ID('ConcatStr') is not null drop table Concat ...

  2. 【转载】配置文件 .yml 写法小结

    配置文件 .yml 写法小结 原文链接:https://www.jianshu.com/p/a8252bf2a63d yaml 是什么? 在 github 一些开源项目里经常可以看到 .travis. ...

  3. 曾经用过的Sql Server分页方法小结

    工作这些年, 数据库分页也用过几种方案, 总结如下: 1.用row_number函数及临时表分页, 适用sql 2005/2008. 大致思路如下: SELECT *, ROW_NUMBER() OV ...

  4. DataGrid分页使用小结

      默认分页模式: 选中"允许分页":页大小:页导航设置,可以是上下方式,也可以用页码方式 格式里可以设置"页导航"按钮的对起方式: private void ...

  5. 新工作上班九天心得(附 bootstrap分页写法)

    2019独角兽企业重金招聘Python工程师标准>>> 新工作上班第九天了.写写自己的心得. 新工作第三天,分配了一个项目,一个开发组长,三个开发人员,一个月完成.开发人员:1. 苏 ...

  6. oracle 分页写法

    select * from (select ROWNUM RN ,TT.* from ( select * from YQ_FEED_BACK_MESSAGE WHERE MODEL_TYPE = 3 ...

  7. 创客学院知识巩固-07驱动初级小结

    文章目录 知识框图: 驱动 字符设备驱动框架 模块传参与符号导出 最简单的字符设备驱动LED灯 IO模型 阻塞 非阻塞 IO多路复用 异步通知--信号驱动 中断与时钟 中断底半部 定时器 内存分配 设 ...

  8. oracle 分页_80分页查询,不止写法

    据孔老先生说,茴香豆的茴字有四种写法,那oracle的分页查询又有多少种写法呢? 分页查询,其实本质上就是topN查询的变种, 如果把topN的一部分结果集去掉,就变成了分页. topN的基本写法,两 ...

  9. 注解分页查询 oracle,oracle分页查询的三种常见写法

    oracle分页查询的三种常见写法分页写法: –分页查询一select * from (select rownum r,e1.* from (select * from emp order by sa ...

最新文章

  1. android 初始化语言,3.4.1 Android初始化语言(1)
  2. python 英语翻译 excel_python批量将excel内容进行翻译写入功能
  3. 如何写一份优秀的Java程序员简历?
  4. Java学习笔记(四)--数据类型与运算符
  5. ECC椭圆曲线算法(3)加密解密过程
  6. Loj#6053-简单的函数【Min25筛】
  7. 计算机应用基础ppt百度文库,计算机应用基础课件(最新版).ppt
  8. 爱立信、EMC笔试面试
  9. 6603网狐棋牌搭建视频教程
  10. “天天向上”力量的Python教学实例
  11. 抢购软件使用方法(如何开发抢购软件)
  12. Azkaban 任务调度系统(使用和小技巧)
  13. Flash应用之百宝箱
  14. PC与S7 1200PLC通讯
  15. 爬虫抓取究竟是什么?
  16. Android开发中Post方式上传文件(头像之类的)
  17. 零假设(Null Hypothesis)
  18. adb命令之:手机与电脑文件之间的粘贴复制
  19. 干货 :超详细的AI 专家路线图!
  20. 自动驾驶系统的传感器标定方法

热门文章

  1. ExtJS学习笔记3:载入、提交和验证表单
  2. 菜鸟学Linux命令:ssh命令 远程登录
  3. NodeJS学习笔记: RESTful —— 为本系列做个小结
  4. CSS SANS – 神奇!使用 CSS3 创建的字体
  5. __cdecl __stdcall区别-转
  6. ubuntu12.04中sublime输入中文
  7. ACCP学习旅程之-----使用C#开发数据库应用程序(第二章)
  8. GoCart 分类和产品 测试一
  9. 深度剖析Zabbix Web scenarios数据表结构
  10. Oracle RAC禁用DRM