日期:2014-05-20  浏览次数:20452 次

分页控件之分页算法 —— for SQL Server 版。百万级的数据只需要15毫秒到900毫秒

下载分页控件(包括源码和演示)

分页控件使用方法

关于分页的误区
  误区1:分页的时候,只有使用存储过程,效率才高。
  误区2:忽略了索引的作用。

上两篇好像介绍的不太详细,这里详细说明一下分页控件里使用的分页算法,也就是SQL语句。

分页一般分为四种情况

1、单字段排序,排序字段没有重复值。
2、单字段排序,排序字段有重复值。
3、多字段排序,最后一个排序字段没有重复值。
4、多字段排序,最后一个排序字段有重复值。

其中第2、4 情况都可以再加一个排序字段(比如说主键),就可以转换成第三种情况。

所以分页针对1、3两种情况设置了两种分页算法。

1、单字段排序,排序字段没有重复值。

  公式:

 1declare @col int
 2
 3select top {PageSize * (PageIndex-1)+1} @col = [排序字段] 
 4from [表名|视图名] 
 5[ where 查询条件 ] 
 6order by [排序字段] asc|desc
 7
 8select top PageSize 需要显示的字段 
 9from [表名|视图名] 
10where [排序字段] >= @col
11[ and 查询条件 ]
12order by [排序字段] asc|desc
  以NorthWind 数据库里的 Products 表为例,假设一页显示10条数据,CategoryID = 3 为查询条件,按照ProductID 倒序,如果想显示第二页的数据,那么SQL语句就是
  declare @col int

select top 11 @col = ProductID from Products where CategoryID = 3 order by ProductID desc  

select top 10 * from Products where ProductID >= @col and CategoryID = 3 order by ProductID desc  
  说明:
  第一行的定义,要根据字段类型来修改,看是比较麻烦,但是这个麻烦交给分页控件就可以了,使用者,只要设置分页控件的属性就可以了。
  第五行和第十一行,如果需要加查询条件的话就可以在这里添加。

  第三行是一个“定位”,这个可以算是SQL Server 所特有的吧,也是SQL Server 很宽容的地方。以Products 表的例子,执行完第一条select 语句之后, @col 里面记录的是 在CategoryID = 3 的记录里面,按照ProductID 倒序,排行在11位的记录的值。
   
  第一个select 语句定位以后,第二个select 语句就可以根据这个“位置”继续向下查找数据了。

  虽然例子里面使用了ProductID(主键)来排序,但是并不是说这个算法只能用主键来排序,哪个字段都可以,但是要符合第一种情况,就是“只有一个排序字段,且排序字段里的记录没有重复值”!


3、多字段排序,最后一个排序字段没有重复值。

  如果 Products 表想要用 UnitPrice 字段来排序怎么办呢?上面的算法是不适合的,我们需要使用另一种算法,这个和颠颠倒倒法有些类似,但是我做了一些优化。

  公式:
select [需要显示的字段] from [表名|视图名] where [主键字段] in 

  ( select top PageSize [主键字段] from 
  (select top {PageSize * PageIndex} [主键字段] , [排序字段] from --有几个排序字段就写几个字段

  [表名|视图名] 
  [ where 查询条件 ] 
  order by 
   
  [排序字段1] asc|desc ,
  [排序字段2] desc|asc, 
   
  [主键字段] asc|desc  
  ) as aa  
  order by  
  [排序字段1] desc|asc, --如果上面是倒序,那么这里就是正序,下同
  [排序字段2] asc|desc ,
   
  [主键字段] desc|asc 

  ) 

order by 
  [排序字段1] asc|desc, --如果上面是倒序,那么这里就是正序,所谓颠颠倒倒嘛。
  [排序字段2] desc|asc,
   
  [主键字段] asc|desc
  以NorthWind 数据库里的 Products 表为例,假设一页显示10条数据,CategoryID = 3 为查询条件,按照UnitPrice 倒序,由于UnitPrice 字段可能有重复值,所以加上一个排序字段——ProductID ,即按照 UnitPrice desc,ProductID 来排序。 如果想显示第二页的数据,那么SQL语句就是
select * from Products where ProductID in 
  ( select top 10 ProductID from 
  (select top 20 ProductID , UnitPrice from  
  Products 
  where CategoryID = 3
  order by 
  UnitPrice desc ,
  ProductID  
  ) as aa  
  order by  
  UnitPrice asc, --如果上面是倒序,那么这里就是正序,下同
  ProductID desc 
  ) 
order by 
  UnitPrice desc, --如果上面是倒序,那么这里就是正序,所谓颠颠倒倒嘛。
  ProductID 
  说明:
  1、这里查询条件加一次就可以了。
  2、是不是看 asc|desc 倒来倒去的有点晕,恩,这就对了,颠颠倒倒嘛。
  3、最主要的就是第三个select 语句,他要取从第一条数据到要显示的页的数据,可见越是后面的记录,top n 就会越大,所以这里提取的数据就要做一个精简,只写排序需要的字段(主键字段和排序字段)。