方法1:
适用于 SQL Server 2000/2005
FROM table1
WHERE id NOT IN
(
SELECT TOP 页大小 * (页数 - 1 ) id FROM table1 ORDER BY id
)
ORDER BY id
方法2:
适用于 SQL Server 2000/2005
FROM table1
WHERE id >
(
SELECT ISNULL ( MAX (id), 0 )
FROM
(
SELECT TOP 页大小 * (页数 - 1 ) id FROM table1 ORDER BY id
) A
)
ORDER BY id
方法3:
适用于 SQL Server 2005
FROM
(
SELECT ROW_NUMBER() OVER ( ORDER BY id) AS RowNumber, * FROM table1
) A
WHERE RowNumber > 页大小 * (页数 - 1 )
说明,页大小:每页的行数;页数:第几页。使用时,请把“页大小”和“页大小*(页数-1)”替换成数字。
其它的方案:如果没有主键,可以用临时表,也可以用方案三做,但是效率会低。
建议优化的时候,加上主键和索引,查询效率会提高。
通过SQL 查询分析器,显示比较:我的结论是:
分页方案二:(利用ID大于多少和SELECT TOP分页)效率最高,需要拼接SQL语句
分页方案一:(利用Not In和SELECT TOP分页) 效率次之,需要拼接SQL语句
分页方案三:(利用SQL的游标存储过程分页) 效率最差,但是最为通用
/*
名称:spAll_ReturnRows
输入:
输出:
调用:
EXEC spAll_ReturnRows 'select * FROM 表名', 页号, 返回记录数, '主键', '排序字段'
spAll_ReturnRows 'select * FROM all_Categories',2,10,'[ID]','[ID]'
说明:[百万级]通用存储过程.分页存储过程..返回指定返回条数、指定页数的记录
作者:Dili J.F. Senders
邮件:diliatwellknow.net
更新:20040610
版权:转述时请注明来源:用思维创造未来的Wellknow.net
*/
create PROCEDURE dbo.spAll_ReturnRows
(
@SQL nVARCHAR ( 4000 ),
@Page int ,
@RecsPerPage int ,
@ID VARCHAR ( 255 ),
@Sort VARCHAR ( 255 )
)
AS
DECLARE @Str nVARCHAR ( 4000 )
SET @Str = ' select TOP ' + cast ( @RecsPerPage AS VARCHAR ( 20 )) + ' * FROM ( ' + @SQL + ' ) T where T. ' + @ID + ' NOT IN
(select TOP ' + cast (( @RecsPerPage * ( @Page - 1 )) AS VARCHAR ( 20 )) + ' ' + @ID + ' FROM ( ' + @SQL + ' ) T9 ORDER BY ' + @Sort + ' ) ORDER BY ' + @Sort
PRINT @Str
EXEC sp_ExecuteSql @Str
GO
/*
名称:spAll_deleteNoneUnique
输入:要查询的表名和字段列表
输出:
调用:
说明:实现千万级数据的分页显示!--可以在5秒内获取1448万条记录里的第1200页的100条记录,雄不?
作者:铁拳版权:转述时请注明来源:用思维创造未来的Wellknow.net
*/
create PROCEDURE GetRecordFromPage
@tblName varchar ( 255 ), -- 表名
@fldName varchar ( 255 ), -- 字段名
@PageSize int = 10 , -- 页尺寸
@PageIndex int = 1 , -- 页码
@IsCount bit = 0 , -- 返回记录总数, 非 0 值则返回
@OrderType bit = 0 , -- 设置排序类型, 非 0 值则降序
@strwhere varchar ( 1000 ) = '' -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL varchar ( 6000 ) -- 主语句
declare @strTmp varchar ( 100 ) -- 临时变量
declare @strOrder varchar ( 400 ) -- 排序类型
if @OrderType != 0
begin
set @strTmp = " < ( select min "
set @strOrder = " order by [ " + @fldName +" ] desc "
end
else
begin
set @strTmp = " > ( select max "
set @strOrder = " order by [ " + @fldName +" ] asc "
end
set @strSQL = " select top " + str ( @PageSize ) + " * from [ "
+ @tblName + " ] where [ " + @fldName + " ] " + @strTmp + "( [ "
+ @fldName + " ] ) from ( select top " + str (( @PageIndex - 1 ) * @PageSize ) + " [ "
+ @fldName + " ] from [ " + @tblName + " ] " + @strOrder + ") as tblTmp)"
+ @strOrder
if @strwhere != ''
set @strSQL = " select top " + str ( @PageSize ) + " * from [ "
+ @tblName + " ] where [ " + @fldName + " ] " + @strTmp + "( [ "
+ @fldName + " ] ) from ( select top " + str (( @PageIndex - 1 ) * @PageSize ) + " [ "
+ @fldName + " ] from [ " + @tblName + " ] where " + @strwhere + " "
+ @strOrder + ") as tblTmp) and " + @strwhere + " " + @strOrder
if @PageIndex = 1
begin
set @strTmp = ""
if @strwhere != ''
set @strTmp = " where " + @strwhere
set @strSQL = " select top " + str ( @PageSize ) + " * from [ "
+ @tblName + " ] " + @strTmp + " " + @strOrder
end
if @IsCount != 0
set @strSQL = " select count ( * ) as Total from [ " + @tblName + " ] "
exec ( @strSQL )
GO
个人研究百万级数据提出问题总结如下:
1 .除了提高硬件方面
2 .采取折中方法,一次提出几百万数据也没有什么实在意义
不过存储过程写的还是很精妙。
p = pagesize,n为返回页数,SQL = " select * from product where id < 200000 "
1 .( select * from product where id < 200000 ) as t
2 .( select top p * (n - 1 ) t.id from t order by id asc ) as t1
3 . select top p * from t where id not in t1 order by id asc
SQL:
select top p * from ( select * from product where id < 200000 ) t where t.id not in ( select top p * (n - 1 ) id from t order by id asc ) order by id asc
[ 注:子查询里面别名t 其实并不存在,应该用1.重新代替 ]
SQL存储过程:
SET @str = ' select top ' + cast ( @p as varchar ( 20 )) + ' * from ( ' + @SQL + ' ) t where t. ' + @ID + ' not in (select top ' + cast (( @p * ( @n - 1 )) as varchar ( 20 )) + ' ' + @ID + ' from ( ' + SQL + ' ) order by ' + @Sort + ' ) order by ' + @Sort
PRINT @str
/*
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wind8303/archive/2009/02/21/3917862.aspx
*/
百万级数据测试结果如下:
//
///result:100W数据
///
///条件:VirtualItemCount=200000
///->转1页 33.924982085712 milliseconds,33.3696042374101 milliseconds,31.1483722093171 milliseconds
///->转1000页 247.380882207096 milliseconds,190.643224208663 milliseconds,240.085262233049 milliseconds
///->转10000页 2393.90201827327 milliseconds,1903.65535284512 milliseconds,1839.06278591273 milliseconds
///
///条件:VirtualItemCount=all
///->1 10.2540965402027 milliseconds,7.47608983823363 milliseconds,15.5991892824367 milliseconds
///->1000 273.380555349912 milliseconds,190.414982909839 milliseconds,217.308345055028 milliseconds
///->10000 1845.92064075183 milliseconds,1951.84974626663 milliseconds,1904.51831168487 milliseconds
///
///2s处理百万数据
//
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wind8303/archive/2009/02/21/3917862.aspx