Sqlserver数据库分页查询一直是Sqlserver的短板,闲来无事,想出几种方法,假设有表ARTICLE,字段ID、YEAR...(其他省略),数据53210条(客户真实数据,量不大),分页查询每页30条,查询第1500页(即第45001-45030条数据),字段ID聚集索引,YEAR无索引,Sqlserver版本:2008R2
第一种方案、最简单、普通的方法:
SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 45000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC
平均查询100次所需时间:45s
第二种方案:
SELECT * FROM ( SELECT TOP 30 * FROM (SELECT TOP 45030 * FROM ARTICLE ORDER BY YEAR DESC, ID DESC) f ORDER BY f.YEAR ASC, f.ID DESC) s ORDER BY s.YEAR DESC,s.ID DESC
平均查询100次所需时间:138S
第三种方案:
SELECT * FROM ARTICLE w1,
(
SELECT TOP 30 ID FROM
(
SELECT TOP 50030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC
平均查询100次所需时间:21S
第四种方案:
SELECT * FROM ARTICLE w1
WHERE ID in
(
SELECT top 30 ID FROM
(
SELECT top 45030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
)
ORDER BY w1.YEAR DESC, w1.ID DESC
平均查询100次所需时间:20S
第五种方案:
SELECT w2.n, w1.* FROM ARTICLE w1, ( SELECT TOP 50030 row_number() OVER (ORDER BY YEAR DESC, ID DESC) n, ID FROM ARTICLE ) w2 WHERE w1.ID = w2.ID AND w2.n > 50000 ORDER BY w2.n ASC
平均查询100次所需时间:15S
查询第1000-1030条记录
第一种方案:
SELECT TOP 30 * FROM ARTICLE WHERE ID NOT IN(SELECT TOP 1000 ID FROM ARTICLE ORDER BY YEAR DESC, ID DESC) ORDER BY YEAR DESC,ID DESC
平均查询100次所需时间:80s
第二种方案:
SELECT * FROM ( SELECT TOP 30 * FROM (SELECT TOP 1030 * FROM ARTICLE ORDER BY YEAR DESC, ID DESC) f ORDER BY f.YEAR ASC, f.ID DESC) s ORDER BY s.YEAR DESC,s.ID DESC
平均查询100次所需时间:30S
第三种方案:
SELECT * FROM ARTICLE w1,
(
SELECT TOP 30 ID FROM
(
SELECT TOP 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
) w2 WHERE w1.ID = w2.ID ORDER BY w1.YEAR DESC, w1.ID DESC
平均查询100次所需时间:12S
第四种方案:
SELECT * FROM ARTICLE w1
WHERE ID in
(
SELECT top 30 ID FROM
(
SELECT top 1030 ID, YEAR FROM ARTICLE ORDER BY YEAR DESC, ID DESC
) w ORDER BY w.YEAR ASC, w.ID ASC
)
ORDER BY w1.YEAR DESC, w1.ID DESC
平均查询100次所需时间:13S
第五种方案:
SELECT w2.n, w1.* FROM ARTICLE w1,( SELECT TOP 1030 row_number() OVER (ORDER BY YEAR DESC, ID DESC) n, ID FROM ARTICLE) w2 WHERE w1.ID = w2.ID AND w2.n > 1000 ORDER BY w2.n ASC
平均查询100次所需时间:14S
由此可见在查询页数靠前时,效率3>4>5>2>1,页码靠后时5>4>3>1>2,再根据用户习惯,一般用户的检索只看最前面几页,因此选择3 4 5方案均可,若综合考虑方案5是最好的选择,但是要注意SQL2000不支持row_number()函数,由于时间和条件的限制没有做更深入、范围更广的测试,有兴趣的可以仔细研究下。
以下是根据第四种方案编写的一个分页存储过程:
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sys_Page_v2]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[sys_Page_v2]
GO
CREATE PROCEDURE [dbo].[sys_Page_v2]
@PCount int output, --总页数输出
@RCount int output, --总记录数输出
@sys_Table nvarchar(100), --查询表名
@sys_Key varchar(50), --主键
@sys_Fields nvarchar(500), --查询字段
@sys_Where nvarchar(3000), --查询条件
@sys_Order nvarchar(100), --排序字段
@sys_Begin int, --开始位置
@sys_PageIndex int, --当前页数
@sys_PageSize int --页大小
AS
SET NOCOUNT ON
SET ANSI_WARNINGS ON
IF @sys_PageSize < 0 OR @sys_PageIndex < 0
BEGIN
RETURN
END
DECLARE @new_where1 NVARCHAR(3000)
DECLARE @new_order1 NVARCHAR(100)
DECLARE @new_order2 NVARCHAR(100)
DECLARE @Sql NVARCHAR(4000)
DECLARE @SqlCount NVARCHAR(4000)
DECLARE @Top int
if(@sys_Begin <=0)
set @sys_Begin=0
else
set @sys_Begin=@sys_Begin-1
IF ISNULL(@sys_Where,'') = ''
SET @new_where1 = ' '
ELSE
SET @new_where1 = ' WHERE ' + @sys_Where
IF ISNULL(@sys_Order,'') <> ''
BEGIN
SET @new_order1 = ' ORDER BY ' + Replace(@sys_Order,'desc','')
SET @new_order1 = Replace(@new_order1,'asc','desc')
SET @new_order2 = ' ORDER BY ' + @sys_Order
END
ELSE
BEGIN
SET @new_order1 = ' ORDER BY ID DESC'
SET @new_order2 = ' ORDER BY ID ASC'
END
SET @SqlCount = 'SELECT @RCount=COUNT(1),@PCount=CEILING((COUNT(1)+0.0)/'
+ CAST(@sys_PageSize AS NVARCHAR)+') FROM ' + @sys_Table + @new_where1
EXEC SP_EXECUTESQL @SqlCount,N'@RCount INT OUTPUT,@PCount INT OUTPUT',
@RCount OUTPUT,@PCount OUTPUT
IF @sys_PageIndex > CEILING((@RCount+0.0)/@sys_PageSize) --如果输入的当前页数大于实际总页数,则把实际总页数赋值给当前页数
BEGIN
SET @sys_PageIndex = CEILING((@RCount+0.0)/@sys_PageSize)
END
set @sql = 'select '+ @sys_fields +' from ' + @sys_Table + ' w1 '
+ ' where '+ @sys_Key +' in ('
+'select top '+ ltrim(str(@sys_PageSize)) +' ' + @sys_Key + ' from '
+'('
+'select top ' + ltrim(STR(@sys_PageSize * @sys_PageIndex + @sys_Begin)) + ' ' + @sys_Key + ' FROM '
+ @sys_Table + @new_where1 + @new_order2
+') w ' + @new_order1
+') ' + @new_order2
print(@sql)
Exec(@sql)
GO
相关推荐
sqlserver分页查询语句;sqlserver分页查询语句;sqlserver分页查询语句;
sql server2005 分页查询语句
mybatis中,sqlserver分页
java 连接sqlserver数据库查询,并分页显示
sql server分页代码 --分页【top】:不支持复合主键 SELECT TOP 10 * from Lend where id not in (SELECT TOP ((2-1)*10) id from lend ORDER BY id) ORDER BY id ; SELECT TOP 10 * from Lend where id not ...
SQLServer数据库的分页查询,比较全面。
通常多表联查并且数据大时,分页查询时,会出现查询性能问题,查分页后面的数据,时间越久。但我们可以通过判断查询数据的总数据来进行相应的查询方式,从而保证性能。
mysql,oracle,sqlserver分页
sqlserver2008不支持关键字limit ,所以它的分页sql查询语句将不能用MySQL的方式进行,幸好sqlserver2008提供了top,rownumber等关键字,这样就能通过这几个关键字实现分页。 下面是本人在网上查阅到的几种查询脚本...
sql server分页技术 详解 sql server分页技术 详解 sql server分页技术 详解
sqlserver分页sql
sql Server 通用分页存储过程 sql Server 通用分页存储过程 sql Server 通用分页存储过程 sql Server 通用分页存储过程
SQL server2008中通用分页存储过程,表名,每页长度,页码都是动态赋值。
这里有两个分页查询的例子,很好看懂,所以没有写注释
关于SQL Server SQL语句查询分页数据的解决方案
sql server 分页大全, 分页存储过程,分页TSQL , 分页语法,语句! 最全的SQL Server2000 分页方法。 可放心下载
java语言编写的分页功能。很实用的查询功能,不基于任何框架的限制。
千万级数据分页查询存储过程SQLServer 有实例
sqlserver+group by分组查询分页存储过程
Sqlserver数据库分页查询一直是Sqlserver的短板,分页查询每页30条,查询第1500页(即第45001-45030条数据)进行测试,分析出最高效的查询,感兴趣的朋友可以参考下哈