sql分页查询几种写法

关于sql语句分页,网上也有很多,我贴一部分过来,并且总结自己已知的分页到下面,方便日后查阅

1.创建测试环境

,(插入100万条数据大概耗时5分钟)。

rush:sql;"> create database DBTest use DBTest

--创建测试表
create table pagetest
(
id int identity(1,1) not null,col01 int null,col02 nvarchar(50) null,col03 datetime null
)

--1万记录集
declare @i int
set @i=0
while(@i<10000)
begin
insert into pagetest select cast(floor(rand()*10000) as int),left(newid(),10),getdate()
set @i=@i+1
end

2.几种典型的分页sql

下面例子是每页50条,198*50=9900,取第199页数据。

--写法1,not in/top

rush:sql;"> select top 50 * from pagetest where id not in (select top 9900 id from pagetest order by id) order by id

--写法2,not exists


rush:sql;"> select top 50 * from pagetest where not exists (select 1 from (select top 9900 id from pagetest order by id)a where a.id=pagetest.id) order by id

--写法3,max/top


(select max(id) from (select top 9900 id from pagetest order by id)a) order by id

--写法4,row_number()


9900

select from
(select row_number()over(order by id)rownumber,
from pagetest)a
where rownumber>9900 and rownumber<9951

select from
(select row_number()over(order by id)rownumber,
from pagetest)a
where rownumber between 9901 and 9950

--写法5,在csdn上一帖子看到的,row_number() 变体,不基于已有字段产生记录序号,先按条件筛选以及排好序,再在结果集上给一常量列用于产生记录序号

9900

3.分别在1万,10万(取1990页),100(取19900页)记录集下测试。

测试sql:

rush:sql;"> declare @begin_date datetime declare @end_date datetime select @begin_date = getdate() <.....YOUR CODE.....> select @end_date = getdate() select datediff(ms,@begin_date,@end_date) as '毫秒'

1万:基本感觉不到差异。

10万:

4.结论:

分页方法。相比ROW_NUMBER()只支持sql2005及以上版本,max/top有更好的可移植性,能同时适用于sql2000,access。

在这里

PS.上面的分页排序都是基于自增字段id。测试环境还提供了int,nvarchar,datetime类型字段,也可以试试。不过对于非主键没索引的大数据量排序效率应该是很不理想的。

5.简单将ROWNUMBER,max/top的方式封装到存储过程。

rush:sql;"> ROWNUMBER():

ALTER PROCEDURE [dbo].[Proc_sqlPageByRownumber]
(
@tbName VARCHAR(255),--表名
@tbGetFields VARCHAR(1000)= '*',--返回字段
@OrderfldName VARCHAR(255),--排序的字段名
@PageSize INT=20,--页尺寸
@PageIndex INT=1,--页码
@OrderType bit = 0,--0升序,非0降序
@strWhere VARCHAR(1000)='',--查询条件
--@TotalCount INT OUTPUT --返回总记录数
)
AS
-- =============================================
-- Author: allen (liyuxin)
-- Create date: 2012-03-30
-- Description: 分页存储过程(支持多表连接查询)
-- Modify [1]: 2012-03-30
-- =============================================
BEGIN
DECLARE @strsql VARCHAR(5000) --主语句
DECLARE @strsqlCount NVARCHAR(500)--查询记录总数主语句
DECLARE @strOrder VARCHAR(300) -- 排序类型

--------------总记录数---------------
IF ISNULL(@strWhere,'') <>''
SET @strsqlCount='Select @TotalCout=count() from ' + @tbName + ' where 1=1 '+ @strWhere
ELSE SET @strsqlCount='Select @TotalCout=count(
) from ' + @tbName

--exec sp_executesql @strsqlCount,N'@TotalCout int output',@TotalCount output
--------------分页------------
IF @PageIndex <= 0 SET @PageIndex = 1

IF(@OrderType<>0) SET @strOrder=' ORDER BY '+@OrderfldName+' DESC '
ELSE SET @strOrder=' ORDER BY '+@OrderfldName+' ASC '

SET @strsql='SELECT FROM
(SELECT ROW_NUMBER() OVER('+@strOrder+') RowNo,'+ @tbGetFields+' FROM ' + @tbName + ' WHERE 1=1 ' + @strWhere+' ) tb
WHERE tb.RowNo BETWEEN '+str((@PageIndex-1)
@PageSize+1)+' AND ' +str(@PageIndex*@PageSize)

exec(@strsql)
SELECT @TotalCount
END

<div class="jb51code">
<pre class="brush:sql;">
public static SqlParameter MakeInParam(string ParamName,SqlDbType DbType,Int32 Size,object Value)
{
return MakeParam(ParamName,DbType,Size,ParameterDirection.Input,Value);
}
public static SqlParameter MakeOutParam(string ParamName,SqlDbType DbType)
{
return MakeParam(ParamName,ParameterDirection.Output,null);
}
public static SqlParameter MakeParam(string ParamName,ParameterDirection Direction,object Value)
{
SqlParameter param;
if (Size > 0)
param = new sqlParameter(ParamName,Size);
else
param = new sqlParameter(ParamName,DbType);
param.Direction = Direction;
if (!(Direction == ParameterDirection.Output && Value == null))
param.Value = Value;
return param;
}
///


/// 分页获取数据列表及总行数
///

/// <param name="tbName">表名
/// <param name="tbGetFields">返回字段
/// <param name="OrderFldName">排序的字段名
/// <param name="PageSize">页尺寸
/// <param name="PageIndex">页码
/// <param name="OrderType">false升序,true降序
/// <param name="strWhere">查询条件
public static DataSet GetPagelist(string tbName,string tbGetFields,string OrderFldName,int PageSize,int PageIndex,string strWhere)
{
sqlParameter[] parameters = {
MakeInParam("@tbName",sqlDbType.VarChar,255,tbName),MakeInParam("@tbGetFields",1000,tbGetFields),MakeInParam("@OrderfldName",OrderFldName),MakeInParam("@PageSize",sqlDbType.Int,PageSize),MakeInParam("@PageIndex",PageIndex),MakeInParam("@OrderType",sqlDbType.Bit,OrderType),MakeInParam("@strWhere",strWhere),// MakeOutParam("@TotalCount",sqlDbType.Int)
};
return RunProcedure("Proc_sqlPageByRownumber",parameters,"ds");
}

调用

rush:sql;"> public DataTable GetList(string tbName,string strWhere,ref int TotalCount) { DataSet ds = dal.GetList(tbName,tbGetFields,OrderFldName,PageSize,PageIndex,strWhere); TotalCount = Convert.ToInt32(ds.Tables[1].Rows[0][0]); return ds.Tables[0]; }


1.必填项:tbName,OrderfldName,tbGetFields


2.实例:

rush:sql;"> tbName =“UserInfo u INNER JOIN Department d ON u.DepID=d.ID” tbGetFields=“u.ID AS UserID,u.Name,u.Sex,d.ID AS DepID,d.DefName” OrderfldName=“u.ID,ASC|u.Name,DESC” (格式:Name,ASC|ID,DESC) strWhere:每个条件前必须添加 AND (例如:AND UserInfo.DepID=1 )

Max/top:(简单写了下,需要满足主键字段名称就是"id")

rush:sql;"> create proc [dbo].[spsqlPageByMaxTop] @tbName varchar(255),--表名 @tbFields varchar(1000),--返回字段 @PageSize int,--页尺寸 @PageIndex int,--页码 @strWhere varchar(1000),--查询条件 @StrOrder varchar(255),--排序条件 @Total int output --返回总记录数 as declare @strsql varchar(5000) --主语句 declare @strsqlCount nvarchar(500)--查询记录总数主语句

--------------总记录数---------------
if @strWhere !=''
begin
set @strsqlCount='Select @TotalCout=count() from ' + @tbName + ' where '+ @strWhere
end
else
begin
set @strsqlCount='Select @TotalCout=count(
) from ' + @tbName
end
--------------分页------------
if @PageIndex <= 0
begin
set @PageIndex = 1
end

set @strSql='select top '+str(@PageSize)+' from ' + @tbName + '
where id>(select max(id) from (select top '+str((@PageIndex-1)
@PageSize)+' id from ' + @tbName + ''+@strOrder+')a)
'+@strOrder+''

exec sp_executesql @strsqlCount,@Total output
exec(@strsql)

园子里搜到Max/top这么一个版本,看起来很强大,

调用

rush:sql;"> declare @count int --exec [dbo].[spsqlPageByRownumber]'pagetest','*',50,20,'','order by id asc',@count output exec [dbo].[spsqlPageByMaxTop]'pagetest',@count output select @count

以上就是本文针对sql分页查询几种写法的全部内容,希望大家喜欢。

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...