select top 11 @id = ID from Table select top 10 * from Table where ID >= @ID (公式:PageSize * (PageIndex - 1) + 1 = 11)
A 高效算法
这是一个非常追求效率的算法,依据MSSQL的特性,为简单分页的情况量身定做的。
第一个特性:select top 11 @id = ID from Table
Top 和 给变量赋值都是很常用的方法,但是这种组合不太常见吧。这是我在一个偶然的情况下发现的,这么写有什么作用呢?先来看看@id会得到什么值。@id 得到的是最后一条记录的ID字段的值,前面的记录的值会被覆盖。
假设分页要求是:每页显示10条记录,按照ID字段升序显示。那么这时候 select top 10 * from Table where ID >= @ID 得到的记录集就是第二页所需要的数据。第三页的数据只要把第一个语句 top 后面的 “11”改成“21”就可以了。公式:PageSize * (PageIndex - 1) + 1
要想使用这个特性必须满足几个条件:排序字段只能有一个,排序字段的值不能有太多重复的,有重复值会造成分页不准,甚至无法翻到下一页的情况。所以这个算法只适用于“简单分页”的情况。不过好在一个网站里面有很多情况都是“简单分页”的情况,随意这个算法还是有价值的。
Ps:这个特性好像只有MSSQL才有,SQLAnywhere是不容许这样写的,除非记录集只有一条记录,oracle 根本就没有top,其它的数据库没有研究过。
思路:先定位(数数),后取记录集(ID >= 的方法)。
优点:第一个语句只取一个字段,即使是top 10000也可以把占用的资源降到最低。如果排序字段有索引的话效果更佳。
哪位能提供完整实例呀(结合AspNetPager控件的)。写了大半天写不出来。有点郁闷的。

解决方案 »

  1.   

    CREATE PROCEDURE dbo.P_Pager
    @strTable       varchar(500),   --表名   
        @strColumn      varchar(50),   --按该列来进行分页   
        @intColType     int,           --@strColumn列的类型,0-数字类型,1-字符类型,2-日期时间类型   
        @intOrder       bit,           --排序,0-顺序,1-倒序   
        @strColumnlist  varchar(800),  --要查询出的字段列表,*表示全部字段   
        @intPageSize    int,           --每页记录数   
        @intPageNum     int,           --指定页   
        @strWhere       varchar(800)  --查询条件 
      AS   
      
      DECLARE   @sql    nvarchar(4000) --用于构造SQL语句
      DECLARE   @where1 varchar(800)   --构造条件语句
      DECLARE   @where2 varchar(800)   --构造条件语句
      
      DECLARE @intPageCount int    --总页数   
      DECLARE @intRecordCount int    --总记录数
      
      set @intPageCount = 0
      set @intRecordCount = 0
      
      IF   @strWhere   is   null   or   rtrim(@strWhere)=''   
      -- 为了避免SQL关键字与字段、表名等连在一起,首先为传入的变量添加空格
      BEGIN  --没有查询条件   
          SET   @where1=' WHERE '   
          SET   @where2=' '   
      END   
      ELSE   
      BEGIN  --有查询条件   
          SET   @where1=' WHERE  ('+@strWhere+')  AND  ' 
          SET   @where2=' WHERE  ('+@strWhere+')  '   
      END     set @strColumn = ' ' + @strColumn + ' '
      set @strColumnlist = ' ' + @strColumnlist + ' '
      
      --计算总记录条数
      SET   @sql='SELECT   @intRecordCount=COUNT(*)   FROM   ' + @strTable + @where2  
      EXEC sp_executesql  @sql,N'@intRecordCount   int   OUTPUT',@intRecordCount   OUTPUT 
      
      --构造SQL语句,计算总页数。计算公式为 总页数 = Ceiling ( 记录个数 / 页大小 )  SET   @sql='SELECT   @intPageCount=CEILING((COUNT(*)+0.0)/'
            + CAST(@intPageSize   AS   varchar)
            + ')   FROM   ' + @strTable + @where2     --执行SQL语句,计算总页数,并将其放入@intPageCount变量中  EXEC sp_executesql  @sql,N'@intPageCount   int   OUTPUT',@intPageCount   OUTPUT   --将总页数放到查询返回记录集的第一个字段前,此语句可省略
      --SET  @strColumnlist= Cast(@intPageCount as varchar(30)) + ' as PageCount,' + @strColumnlist   
      IF   @intOrder=0   --构造升序的SQL      SET @sql='SELECT TOP '+ CAST(@intPageSize   AS   varchar)  + 
                   @strColumnlist +   
                   ' FROM ' + @strTable + @where1 + 
                   @strColumn + '>(SELECT MAX('+@strColumn+')  '+   
                   ' FROM (SELECT TOP '+ CAST(@intPageSize*(@intPageNum - 1)  AS  varchar) +   
                   @strColumn + ' FROM '+ @strTable+@where2+'ORDER  BY '+@strColumn+')  t)  ORDER  BY '+ @strColumn     ELSE              --构造降序的SQL         SET @sql='SELECT TOP '+ CAST(@intPageSize   AS   varchar)  + 
                   @strColumnlist+   
                   ' FROM '+ @strTable + @where1 + 
                   @strColumn + '<(SELECT   MIN('+@strColumn+')   '+   
                   ' FROM (SELECT TOP '+ CAST(@intPageSize*(@intPageNum - 1)  AS  varchar) +   
                   @strColumn + ' FROM '+ @strTable+@where2+'ORDER   BY '+@strColumn+'   DESC)   t)   ORDER   BY   '+   
                   @strColumn + ' DESC'          IF   @intPageNum=1--第一页         SET   @sql='SELECT   TOP   '+CAST(@intPageSize   AS   varchar) + @strColumnlist + ' FROM '+@strTable+   
                     @where2+'ORDER   BY   '+@strColumn+CASE   @intOrder WHEN  0 THEN  ''  ELSE  '  DESC'    END   
     
      EXEC(@sql)   
      print @sql
      Select PageCount=@intPageCount,RecordCount=@intRecordCount
    GO
      

  2.   

    USE AdventureWorks;
    GO
    WITH OrderedOrders AS
    (SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (order by OrderDate)as RowNumber
    FROM Sales.SalesOrderHeader ) 
    SELECT * 
    FROM OrderedOrders 
    WHERE RowNumber between 50 and 60;
      

  3.   

    http://www.codeproject.com/useritems/Query_paging_on_SQL_2005.asp