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

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

代码如下:
[sql] view plaincopy
  1. 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

第二种方案:

代码如下:
[sql] view plaincopy
  1. 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

第三种方案:

代码如下:
[sql] view plaincopy
  1. SELECT * FROM ARTICLE w1,
  2. (
  3. SELECT TOP 30 ID FROM
  4. (
  5. SELECT TOP 50030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
  6. ) w ORDER BY w.YEAR ASC, w.ID ASC
  7. ) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC

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

第四种方案:

代码如下:
[sql] view plaincopy
  1. SELECT * FROM ARTICLE w1
  2. WHERE ID in
  3. (
  4. SELECT top 30 ID FROM
  5. (
  6. SELECT top 45030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
  7. ) w ORDER BY w.YEAR ASC, w.ID ASC
  8. )
  9. ORDER BY w1.YEAR DESC, w1.ID DESC

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

第五种方案:

代码如下:
[sql] view plaincopy
  1. 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条记录

第一种方案:

代码如下:
[sql] view plaincopy
  1. 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

第二种方案:

代码如下:
[sql] view plaincopy
  1. 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

第三种方案:

代码如下:
[sql] view plaincopy
  1. SELECT * FROM ARTICLE w1,
  2. (
  3. SELECT TOP 30 ID FROM
  4. (
  5. SELECT TOP 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
  6. ) w ORDER BY w.YEAR ASC, w.ID ASC
  7. ) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC

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

第四种方案:

代码如下:
[sql] view plaincopy
  1. SELECT * FROM ARTICLE w1
  2. WHERE ID in
  3. (
  4. SELECT top 30 ID FROM
  5. (
  6. SELECT top 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
  7. ) w ORDER BY w.YEAR ASC, w.ID ASC
  8. )
  9. ORDER BY w1.YEAR DESC, w1.ID DESC

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

第五种方案:

代码如下:
[sql] view plaincopy
  1. 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()函数,由于时间和条件的限制没有做更深入、范围更广的测试,有兴趣的可以仔细研究下。

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

代码如下:
[sql] view plaincopy
  1. if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sys_Page_v2]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
  2. drop procedure [dbo].[sys_Page_v2]
  3. GO
  4. CREATE PROCEDURE [dbo].[sys_Page_v2]
  5. @PCount int output,    --总页数输出
  6. @RCount int output,    --总记录数输出
  7. @sys_Table nvarchar(100),    --查询表名
  8. @sys_Key varchar(50),        --主键
  9. @sys_Fields nvarchar(500),    --查询字段
  10. @sys_Where nvarchar(3000),    --查询条件
  11. @sys_Order nvarchar(100),    --排序字段
  12. @sys_Begin int,        --开始位置
  13. @sys_PageIndex int,        --当前页数
  14. @sys_PageSize int        --页大小
  15. AS
  16. SET NOCOUNT ON
  17. SET ANSI_WARNINGS ON
  18. IF @sys_PageSize < 0 OR @sys_PageIndex < 0
  19. BEGIN
  20. RETURN
  21. END
  22. DECLARE @new_where1 NVARCHAR(3000)
  23. DECLARE @new_order1 NVARCHAR(100)
  24. DECLARE @new_order2 NVARCHAR(100)
  25. DECLARE @Sql NVARCHAR(4000)
  26. DECLARE @SqlCount NVARCHAR(4000)
  27. DECLARE @Top int
  28. if(@sys_Begin <=0)
  29. set @sys_Begin=0
  30. else
  31. set @sys_Begin=@sys_Begin-1
  32. IF ISNULL(@sys_Where,'') = ''
  33. SET @new_where1 = ' '
  34. ELSE
  35. SET @new_where1 = ' WHERE ' + @sys_Where
  36. IF ISNULL(@sys_Order,'') <> ''
  37. BEGIN
  38. SET @new_order1 = ' ORDER BY ' + Replace(@sys_Order,'desc','')
  39. SET @new_order1 = Replace(@new_order1,'asc','desc')
  40. SET @new_order2 = ' ORDER BY ' + @sys_Order
  41. END
  42. ELSE
  43. BEGIN
  44. SET @new_order1 = ' ORDER BY ID DESC'
  45. SET @new_order2 = ' ORDER BY ID ASC'
  46. END
  47. SET @SqlCount = 'SELECT @RCount=COUNT(1),@PCount=CEILING((COUNT(1)+0.0)/'
  48. + CAST(@sys_PageSize AS NVARCHAR)+') FROM ' + @sys_Table + @new_where1
  49. EXEC SP_EXECUTESQL @SqlCount,N'@RCount INT OUTPUT,@PCount INT OUTPUT',
  50. @RCount OUTPUT,@PCount OUTPUT
  51. IF @sys_PageIndex > CEILING((@RCount+0.0)/@sys_PageSize)    --如果输入的当前页数大于实际总页数,则把实际总页数赋值给当前页数
  52. BEGIN
  53. SET @sys_PageIndex =  CEILING((@RCount+0.0)/@sys_PageSize)
  54. END
  55. set @sql = 'select '+ @sys_fields +' from ' + @sys_Table + ' w1 '
  56. + ' where '+ @sys_Key +' in ('
  57. +'select top '+ ltrim(str(@sys_PageSize)) +' ' + @sys_Key + ' from '
  58. +'('
  59. +'select top ' + ltrim(STR(@sys_PageSize * @sys_PageIndex + @sys_Begin)) + ' ' + @sys_Key + ' FROM '
  60. + @sys_Table + @new_where1 + @new_order2
  61. +') w ' + @new_order1
  62. +') ' + @new_order2
  63. print(@sql)
  64. Exec(@sql)
  65. GO
文章来源:CSDN
作者:语不惊人死不休
查看原文

高效的SQLSERVER分页查询相关推荐

  1. 数据库:SQLServer分页查询整理

    作为程序员来说,与数据库打交道是十分频繁的分页查询是一个开发者必须掌握的基本知识点,目前整理了下面三种SQLServer分页查询语句的写法,仅供参考. 一.Top Not IN 方式(查询靠前的数据较 ...

  2. 三种SQLServer分页查询语句笔记

    作为程序员来说,与数据库打交道是十分频繁的分页查询是一个开发者必须掌握的基本知识点,目前整理了下面三种SQLServer分页查询语句的写法,仅供参考. 一.Top Not IN 方式(查询靠前的数据较 ...

  3. Oracle、 Mysql 、 SQLserver 分页查询

    MYSQL 分页最简单了. SELECT * FROM Account  WHERE (usertype='base' or usertype='home' or usertype='salse')  ...

  4. Sqlserver分页查询语句

    Sql server分页查询语句 PageSize:每页显示几条数据 pageNumber:当前页索引 T为表 注:通常pageNumber索引从零开始 select * from t where I ...

  5. SQLServer分页查询

    OFFSET x ROW FETCH NEXT y ROWS ONLY; 使用OFFSET是SQLServer2012新具有的分页功能,主要功能是从第x条数据开始共取y数据.但是其必须跟在Order ...

  6. 你还不会ElasticsSearch分页查询?那你看这一篇就够了,快拿走吧

    关注.星标下方公众号[ 大数据之美 ],和你一起成长 原文链接:你还不会ElasticsSearch分页查询?那你看这一篇就够了,快拿走吧 引言 我们使用mysql的时候经常遇到分页查询的场景,在my ...

  7. mysql读取第3条记录_sql查询(三)之分页查询

    分页查询这个内容基本上是个项目都会用的到的东西,面试也会问到的, 平常项目中老是百度用法,这些写博客来总结一下,省的老是百度. 现在主流的关系型数据的分页实现还是有点差别的,以oracle.mysql ...

  8. mysql 高效分页查询_PostgreSQL、MySQL高效分页方法探讨

    对于数据库相关的业务,逃不过的数据分页场景,无论是前台分页浏览还是划到页面底部自动加载.对于分页需求,各数据库也提供了成熟的SQL支持,类似于Hibernate等ORM框架也集成了相关的方法.但是基于 ...

  9. oracle mssql 实例,oracle,mysql,SqlServer三种数据库的分页查询的实例

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

最新文章

  1. TCMalloc(Thread-Caching malloc) 基本设计原理
  2. 解决ubuntu里面的sudo: /etc/sudoers is mode 0640, should be 0440
  3. html a标签去掉下划线_让HTML元素动起来
  4. 区块链游戏为何只剩下“炒币”的价值?
  5. C语言函数指针(结构体函数指针)
  6. 【云炬mysql数据库笔记】 Work1
  7. eclipse项目迁移到android studio(图文最新版)
  8. STM32 IO口输入输出模式的简洁见解
  9. 一文说通异步 LINQ
  10. 关于嵌入式可执行程序,你了解多少?
  11. 用python语言写一个简单的计算器
  12. Image Gallery
  13. error: implicit declaration of function ‘VerifyFixClassname‘ is invalid in C99 [-Werror,-Wimplicit-f
  14. 【源码】迭代法求根的matlab算法
  15. mysql sql 字符串拼接_深入讲解SQL中的字符串拼接
  16. sql vb xml 换行_vb中换行代码 vb代码输出怎么换行
  17. Baxter 机器人仿真软件安装及演示
  18. 神兽卡再次进化,华硕正式推出 Essense STX II 与 STX II 7.1 内接式音效卡 ...
  19. 失意的互联网人拼命叩开Web3大门
  20. 【VUE3】Hash模式与HTML5模式使用区别

热门文章

  1. android环境搭建出错,androidstudio配置环境遇到的各种错误(持续更新中)
  2. 空心点_空心砖的新玩法,看完大开眼界
  3. leetcode 二进制求和 addBinary
  4. 最优间隔分类器-SVM
  5. 2019-03-09-算法-进化(旋转数组)
  6. 多项式除法,多项式取模
  7. P3345 [ZJOI2015]幻想乡战略游戏
  8. CF704B. Ant Man
  9. 牛客网【每日一题】5月22日 [CQOI2009]中位数图
  10. [CodeForces gym 102956 D] Bank Security Unification(位运算优化dp)