Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID、YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询每页30条,查询第1500页(即第45001-45030条数据),字段ID聚集索引,YEAR无索引,Sqlserver版本:2008R2

第一种方案、最简单、普通的方法:

SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 45000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC  

平均查询100次所需时间:45s

第二种方案:

SELECT * FROM 
(
  SELECT TOP 30 * FROM (SELECT TOP 45030 * FROM ARTICLE ORDER BY YEAR DESC, ID DESC) f ORDER BY f.YEAR ASC, f.ID DESC
) s ORDER BY s.YEAR DESC,s.ID DESC

平均查询100次所需时间:138S

第三种方案:

SELECT * FROM ARTICLE w1,
(
SELECT TOP 30 ID FROM
(
SELECT TOP 50030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC

平均查询100次所需时间:21S

第四种方案:

SELECT * FROM ARTICLE w1
WHERE ID in
(
SELECT top 30 ID FROM
(
SELECT top 45030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
)
ORDER BY w1.YEAR DESC, w1.ID DESC

平均查询100次所需时间:20S

第五种方案:

SELECT w2.n, w1.* FROM ARTICLE w1, 
(
  SELECT TOP 50030 row_number() OVER (ORDER BY YEAR DESC, ID DESC) n, ID FROM ARTICLE
) w2 WHERE w1.ID = w2.ID AND w2.n > 50000 ORDER BY w2.n ASC

平均查询100次所需时间:15S

查询第1000-1030条记录

第一种方案:

SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 1000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC  

平均查询100次所需时间:80s

第二种方案:

SELECT * FROM  
(
  SELECT TOP 30 * FROM (SELECT TOP 1030 * FROM ARTICLE ORDER BY YEAR DESC, ID DESC) f ORDER BY f.YEAR ASC, f.ID DESC
) s ORDER BY s.YEAR DESC,s.ID DESC

平均查询100次所需时间:30S

第三种方案:

SELECT * FROM ARTICLE w1,
(
SELECT TOP 30 ID FROM
(
SELECT TOP 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC

平均查询100次所需时间:12S

第四种方案:

SELECT * FROM ARTICLE w1
WHERE ID in
(
SELECT top 30 ID FROM
(
SELECT top 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
)
ORDER BY w1.YEAR DESC, w1.ID DESC

平均查询100次所需时间:13S

第五种方案:

SELECT w2.n, w1.* FROM ARTICLE w1,
(
  SELECT TOP 1030 row_number() OVER (ORDER BY YEAR DESC, ID DESC) n, ID FROM ARTICLE
) w2 WHERE w1.ID = w2.ID AND w2.n > 1000 ORDER BY w2.n ASC

平均查询100次所需时间:14S

由此可见在查询页数靠前时,效率3>4>5>2>1,页码靠后时5>4>3>1>2,再根据用户习惯,一般用户的检索只看最前面几页,因此选择3 4 5方案均可,若综合考虑方案5是最好的选择,但是要注意SQL2000不支持row_number()函数,由于时间和条件的限制没有做更深入、范围更广的测试,有兴趣的可以仔细研究下。

以下是根据第四种方案编写的一个分页存储过程:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sys_Page_v2]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[sys_Page_v2]
GO CREATE PROCEDURE [dbo].[sys_Page_v2]
@PCount int output, --总页数输出
@RCount int output, --总记录数输出
@sys_Table nvarchar(100), --查询表名
@sys_Key varchar(50), --主键
@sys_Fields nvarchar(500), --查询字段
@sys_Where nvarchar(3000), --查询条件
@sys_Order nvarchar(100), --排序字段
@sys_Begin int, --开始位置
@sys_PageIndex int, --当前页数
@sys_PageSize int --页大小
AS SET NOCOUNT ON
SET ANSI_WARNINGS ON IF @sys_PageSize < 0 OR @sys_PageIndex < 0
BEGIN
RETURN
END DECLARE @new_where1 NVARCHAR(3000)
DECLARE @new_order1 NVARCHAR(100)
DECLARE @new_order2 NVARCHAR(100)
DECLARE @Sql NVARCHAR(4000)
DECLARE @SqlCount NVARCHAR(4000) DECLARE @Top int if(@sys_Begin <=0)
set @sys_Begin=0
else
set @sys_Begin=@sys_Begin-1 IF ISNULL(@sys_Where,'') = ''
SET @new_where1 = ' '
ELSE
SET @new_where1 = ' WHERE ' + @sys_Where IF ISNULL(@sys_Order,'') <> ''
BEGIN
SET @new_order1 = ' ORDER BY ' + Replace(@sys_Order,'desc','')
SET @new_order1 = Replace(@new_order1,'asc','desc') SET @new_order2 = ' ORDER BY ' + @sys_Order
END
ELSE
BEGIN
SET @new_order1 = ' ORDER BY ID DESC'
SET @new_order2 = ' ORDER BY ID ASC'
END SET @SqlCount = 'SELECT @RCount=COUNT(1),@PCount=CEILING((COUNT(1)+0.0)/'
+ CAST(@sys_PageSize AS NVARCHAR)+') FROM ' + @sys_Table + @new_where1 EXEC SP_EXECUTESQL @SqlCount,N'@RCount INT OUTPUT,@PCount INT OUTPUT',
@RCount OUTPUT,@PCount OUTPUT IF @sys_PageIndex > CEILING((@RCount+0.0)/@sys_PageSize) --如果输入的当前页数大于实际总页数,则把实际总页数赋值给当前页数
BEGIN
SET @sys_PageIndex = CEILING((@RCount+0.0)/@sys_PageSize)
END set @sql = 'select '+ @sys_fields +' from ' + @sys_Table + ' w1 '
+ ' where '+ @sys_Key +' in ('
+'select top '+ ltrim(str(@sys_PageSize)) +' ' + @sys_Key + ' from '
+'('
+'select top ' + ltrim(STR(@sys_PageSize * @sys_PageIndex + @sys_Begin)) + ' ' + @sys_Key + ' FROM '
+ @sys_Table + @new_where1 + @new_order2
+') w ' + @new_order1
+') ' + @new_order2 print(@sql) Exec(@sql) GO

SQLserver分页查询实例的更多相关文章

  1. SQLServer分页查询存储过程

    项目中用到的SQLServer分页查询存储过程. [存储过程] create PROCEDURE prcPageResult -- 获得某一页的数据 -- @currPage int = 1,     ...

  2. 【MySQL】分页查询实例讲解

    MySQL分页查询实例讲解 1. 前言 本文描述了团队在工作中遇到的一个MySQL分页查询问题,顺带讲解相关知识点,为后来者鉴.本文的重点不是"怎样"优化表结构和SQL语句,而是探 ...

  3. 高效的SQLSERVER分页查询的几种示例分析

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

  4. 真正高效的SQLSERVER分页查询(多种方案)

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

  5. SQLSERVER分页查询

    转:http://blog.csdn.net/qiaqia609/article/details/41445233   Sqlserver数据库分页查询一直是Sqlserver的短板,   第一种方案 ...

  6. 高效的SQLSERVER分页查询(推荐)

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

  7. 高效的SQLSERVER分页查询

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

  8. SQLServer分页查询笔记

    学习SqlServer到现在快两年了吧,分页查询总是忘了看笔记,看了又忘.之前用的分页都是row_number函数的方式,背不住...直到今天,看到别人写的另一种分页写法,看似比row_number简 ...

  9. Oracle/MySql/SQL Sqlserver分页查询

    简述 简单概括一下Oracle,MySql,SQL Sqlserver这三个数据库的分页查询语句. Oracle分页查询 例:每页显示两条数据,现在要查询第二页,也就是第3-4条数据. 查询语句: s ...

随机推荐

  1. DELPHI 单元文件结构

    unit Unit1; interface {接口部分开始} uses {引用单元列表,这是可选的,如果包含必须紧跟interface关键字} {接口部分声明常量/类型/变量/过程和函数,这些声明对引 ...

  2. Win10下IIS配置图解、MVC项目发布图解、IIS添加网站图解

    Win10下IIS配置 .找到控制面板:[开始]菜单鼠标右击,打开[控制面板] .打开控制面板,点击[程序],点击[启用或关闭Windows功能] 下一步,点击[启用虎关闭Windows功能] . 开 ...

  3. [terry笔记]RMAN综合学习之配置

    [terry笔记]RMAN综合学习之备份http://www.cnblogs.com/kkterry/p/3308405.html [terry笔记]RMAN综合学习之恢复 http://www.cn ...

  4. java软件包的访问权限和继承

    public:公共权限,可以修饰类.成员变量和成员函数,不论是否在同一个包中均可自由访问 package wang; //当一个类的权限为public时,类名必须和文件名相同 public class ...

  5. 文件系统 第八次迭代 VFS相关说明

    麻烦访问evernote链接 http://www.evernote.com/shard/s133/sh/53e5b5ac-1192-4910-8bd5-6886218562af/59516c32a5 ...

  6. MAC 重置MySQL root 密码

    重置MySQL root 密码:当忘记密码,或者想要强行重置 MySQL 密码的时候,可以像下面这样: 1.停止 MySQL 服务 sudo /usr/local/mysql/support-file ...

  7. hdu 5253 连接的管道

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5253 连接的管道 Description 老 Jack 有一片农田,以往几年都是靠天吃饭的.但是今年老 ...

  8. microsoft azure Media Services 媒体服务解决方案

    用安全的方式为您随时随地跨设备传送媒体内容.提供可伸缩的端到端媒体解决方案 可用于高级视频工作流的云 实现奥运会规模的直播与点播媒体传送 高可用的编码和流式处理 支持 Flash.iOS.Androi ...

  9. IOS之UIView的tag学习

    tag是UIView的一个属性,而且要求tag值唯一.父视图可以通过tag来找到一个子视图 UIView *redView = [[UIView alloc]initWithFrame:CGRectM ...

  10. OC中数组类NSArray的详解,数组的遍历(二)

    数组类的便利 1.for循环(大家都会的...) 2.NSEmunerator 3.for in 首先重点说下 第二种NSEmunerator枚举器,系统声明是 @interface NSEnumer ...