扩展Row_Number分页功能,二分思路。
2009-12-07 15:16
387 查看
近期遇到了数据量比较大的多列排序处理,Top Max模式很难满足多列混合排序的情形,Row_number则可以,但是在末尾的分页效果已经不太如人意了,想了想二分法改造一下比较适合吧。
本存储过程适合多列排序,通用,效率不如单纯的Top Max二分法,但是要配合多列排序,还是能够接受。
相关测试效果依数据量和索引合理性而定。
本存储过程适合多列排序,通用,效率不如单纯的Top Max二分法,但是要配合多列排序,还是能够接受。
if exists(select name from sysobjects where type='p'and name='DataPager') drop PROCEDURE DataPager go Create PROCEDURE [DataPagerTmp] ( @tblName nvarchar(200), ----要显示的表或多个表的连接 @fldName nvarchar(1000)='*', ----要显示的字段列表,一定要包含排序字段 @pageSize int = 10, ----每页显示的记录个数 @page int = 1, ----要显示那一页的记录 @pageCount int = 1 output, ----查询结果分页后的总页数 @Counts int =1 output, ----查询到的记录数 @fldSort nvarchar(100)='', ----如果多列排序,最后一列不能带DESC或ASC,@Sort排序作用于最后一列,反之,单列根据@Sort来处理 @Sort int = 1, ----排序方法,0为升序,1为降序 @strCondition nvarchar(1000)='', ----查询条件,不需where @keyID nvarchar(50) = 'ID' ) /*Create by wszhoho*/ AS declare @sqlTmp nvarchar(2000) declare @sqlGetCount nvarchar(2000) declare @frontOrder nvarchar(200) declare @behindOrder nvarchar(200) declare @start nvarchar(20) declare @end nvarchar(20) begin if @fldSort is null or @fldSort='' set @fldSort=@keyID if charindex(',',@fldSort,0)>0--多列排序,则@Sort排序方法无效 begin if @Sort=1--倒序 set @fldSort = @fldSort + ' Desc' else set @fldSort = @fldSort + ' ASC' set @frontOrder = @fldSort--获取分页前半部分数据的排序规则 set @behindOrder = replace(@frontOrder,'desc','desctmp') set @behindOrder = replace(@behindOrder,'asc','desc') set @behindOrder = replace(@behindOrder,'desctmp','asc')--获取分页后半部分数据的排序规则 end else--单列 begin set @fldSort=replace(replace(@fldSort,'desc',''),'asc','')--替换掉结尾的规则,用@Sort值来处理排序 if @Sort=1--倒序 begin set @frontOrder = @fldSort + ' desc' set @behindOrder = @fldSort + ' asc' end else begin set @frontOrder = @fldSort + ' asc' set @behindOrder = @fldSort + ' desc' end end --获取记录数 if @strCondition is null or @strCondition = ''--无条件 begin set @sqlGetCount = 'select @Counts=count(*) from ' + @tblName end else begin set @sqlGetCount = 'select @Counts=count(*) from ' + @tblName + ' where ' + @strCondition end ----取得查询结果总数量----- exec sp_executesql @sqlGetCount,N'@Counts int out ',@Counts out declare @tmpCounts int if @Counts = 0 set @tmpCounts = 1 else set @tmpCounts = @Counts --取得分页总数 set @pageCount=(@tmpCounts+@pageSize-1)/@pageSize /**当前页大于总页数 取最后一页**/ if @page>@pageCount set @page=@pageCount /*-----数据分页2分处理-------*/ declare @pageIndex int --总数/页大小 declare @lastcount int --总数%页大小 最后一页的数据量 set @pageIndex = @tmpCounts/@pageSize set @lastcount = @tmpCounts%@pageSize if @lastcount > 0 set @pageIndex = @pageIndex + 1 else set @lastcount = @pagesize --取得数据的逻辑分析 if @strCondition is null or @strCondition='' --没有设置显示条件 begin if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2 --前半部分数据处理 begin --计算开始结束的行号 set @start = @pageSize*(@page-1)+1 set @end = @start+@pageSize-1 set @sqlTmp='SELECT ' + @fldName + ' FROM (select '+@fldName+',ROW_NUMBER() OVER ( Order by '+@frontOrder+' ) AS RowNumber From '+@tblName+') T WHERE T.RowNumber BETWEEN '+@start+' AND '+@end+' order by '+@frontOrder end else begin set @page = @pageIndex-@page+1 --后半部分数据处理 if @lastcount=@pageSize --如果正好是整数页 begin set @start = @pageSize*(@page-1)+1 set @end = @start+@pageSize-1 end else begin set @start = @lastcount+@pageSize*(@page-2)+1 set @end = @start+@pageSize-1 end set @sqlTmp='select '+@fldName+' FROM (select '+@fldName+',ROW_NUMBER() OVER ( Order by '+@behindOrder+' ) AS RowNumber From '+@tblName+') T WHERE T.RowNumber BETWEEN '+@start+' AND '+@end+' order by '+@frontOrder end end else --有查询条件 begin if @pageIndex<2 or @page<=@pageIndex / 2 + @pageIndex % 2 --前半部分数据处理 begin --计算开始结束的行号 set @start = @pageSize*(@page-1)+1 set @end = @start+@pageSize-1 set @sqlTmp='SELECT ' + @fldName + ' FROM (select '+@fldName+',ROW_NUMBER() OVER ( Order by '+@frontOrder+' ) AS RowNumber From '+@tblName+' where '+@strCondition+') T WHERE T.RowNumber BETWEEN '+@start+' AND '+@end+' order by '+@frontOrder end else begin set @page = @pageIndex-@page+1 --后半部分数据处理 if @lastcount=@pageSize --如果正好是整数页 begin set @start = @pageSize*(@page-1)+1 set @end = @start+@pageSize-1 end else begin set @start = @lastcount+@pageSize*(@page-2)+1 set @end = @start+@pageSize-1 end set @sqlTmp='select '+@fldName+' FROM (select '+@fldName+',ROW_NUMBER() OVER ( Order by '+@behindOrder+' ) AS RowNumber From '+@tblName+' where '+@strCondition+') T WHERE T.RowNumber BETWEEN '+@start+' AND '+@end+' order by '+@frontOrder end end end exec sp_executesql @sqlTmp --select @sqlTmp
相关测试效果依数据量和索引合理性而定。
相关文章推荐
- ACCESS的分页之道,Access中实现row_number() over()聚合函数功能
- SQL 2005的ROW_NUMBER()实现分页功能
- 用SQL 2005的ROW_NUMBER() 实现分页功能
- SQL2005利用ROW_NUMBER() OVER实现分页功能
- 用SQL2005的ROW_NUMBER()实现分页功能
- 用SQL 2005的ROW_NUMBER() 实现分页功能
- SQL 2005的ROW_NUMBER()实现分页功能(转载)
- SQL 2005的ROW_NUMBER()实现分页的功能
- 用ROW_NUMBER()&nbsp;实现分页功能
- 用SQL 2005的ROW_NUMBER() 实现分页功能
- 用SQL 2005的ROW_NUMBER() 实现分页功能
- SQL 2005的ROW_NUMBER()实现分页功能
- 数据库分页大全(oracle利用解析函数row_number高效分页)
- SQL关于分页的sql查询语句 limit 和row_number() OVER函数
- sql语句分页多种方式ROW_NUMBER()OVER
- sql server 2005的分页函数ROW_NUMBER
- Sql Server 2005 row_number()分页性能测试
- SQL Server利用RowNumber()内置函数与Over关键字实现通用分页存储过程(支持单表或多表结查集分页)
- MSSQL 无标识列 无主键 group by row_number() over() 分页
- MYSQL-实现ORACLE- row_number() over(partition by ) 分组排序功能.