关于高效分页
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控件的)。写了大半天写不出来。有点郁闷的。
[解决办法]
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 @intPageCountint --总页数
DECLARE @intRecordCountint --总记录数
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
[解决办法]
up
[解决办法]
帮你顶!
[解决办法]
好呀,学习,up
[解决办法]
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;