溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

sql中怎么實(shí)現(xiàn)分頁(yè)查詢

發(fā)布時(shí)間:2021-08-04 15:30:27 來(lái)源:億速云 閱讀:218 作者:Leah 欄目:數(shù)據(jù)庫(kù)

本篇文章為大家展示了sql中怎么實(shí)現(xiàn)分頁(yè)查詢,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

1.創(chuàng)建測(cè)試環(huán)境,(插入100萬(wàn)條數(shù)據(jù)大概耗時(shí)5分鐘)。

create database DBTestuse DBTest --創(chuàng)建測(cè)試表create table pagetest(id int identity(1,1) not null,col01 int null,col02 nvarchar(50) null,col03 datetime null) --1萬(wàn)記錄集declare @i intset @i=0while(@i<10000)begin insert into pagetest select cast(floor(rand()*10000) as int),left(newid(),10),getdate() set @i=@i+1end

2.幾種典型的分頁(yè)sql,下面例子是每頁(yè)50條,198*50=9900,取第199頁(yè)數(shù)據(jù)。

--寫法1,not in/top

select top 50 * from pagetestwhere id not in (select top 9900 id from pagetest order by id)order by id

--寫法2,not exists

select top 50 * from pagetestwhere 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 top 50 * from pagetestwhere id>(select max(id) from (select top 9900 id from pagetest order by id)a)order by id

--寫法4,row_number()

select top 50 * from(select row_number()over(order by id)rownumber,* from pagetest)awhere rownumber>9900 select * from(select row_number()over(order by id)rownumber,* from pagetest)awhere rownumber>9900 and rownumber<9951 select * from(select row_number()over(order by id)rownumber,* from pagetest)awhere rownumber between 9901 and 9950

--寫法5,在csdn上一帖子看到的,row_number() 變體,不基于已有字段產(chǎn)生記錄序號(hào),先按條件篩選以及排好序,再在結(jié)果集上給一常量列用于產(chǎn)生記錄序號(hào)

select *from ( select row_number()over(order by tempColumn)rownumber,* from (select top 9950 tempColumn=0,* from pagetest where 1=1 order by id)a)bwhere rownumber>9900

3.分別在1萬(wàn),10萬(wàn)(取1990頁(yè)),100(取19900頁(yè))記錄集下測(cè)試。

測(cè)試sql:

declare @begin_date datetimedeclare @end_date datetimeselect @begin_date = getdate()<.....YOUR CODE.....>select @end_date = getdate()select datediff(ms,@begin_date,@end_date) as '毫秒'

1萬(wàn):基本感覺(jué)不到差異。

10萬(wàn):

4.結(jié)論:

1.max/top,ROW_NUMBER()都是比較不錯(cuò)的分頁(yè)方法。相比ROW_NUMBER()只支持sql2005及以上版本,max/top有更好的可移植性,能同時(shí)適用于sql2000,access。

2.not exists感覺(jué)是要比not in效率高一點(diǎn)點(diǎn)。

3.ROW_NUMBER()的3種不同寫法效率看起來(lái)差不多。

4.ROW_NUMBER() 的變體基于我這個(gè)測(cè)試效率實(shí)在不好。原帖在這里 http://topic.csdn.net/u/20100617/04/80d1bd99-2e1c-4083-ad87-72bf706cb536.html

PS.上面的分頁(yè)排序都是基于自增字段id。測(cè)試環(huán)境還提供了int,nvarchar,datetime類型字段,也可以試試。不過(guò)對(duì)于非主鍵沒(méi)索引的大數(shù)據(jù)量排序效率應(yīng)該是很不理想的。

5.簡(jiǎn)單將ROWNUMBER,max/top的方式封裝到存儲(chǔ)過(guò)程。

ROWNUMBER():ALTER PROCEDURE [dbo].[Proc_SqlPageByRownumber]( @tbName VARCHAR(255),   --表名 @tbGetFields VARCHAR(1000)= '*',--返回字段 @OrderfldName VARCHAR(255),  --排序的字段名 @PageSize INT=20,    --頁(yè)尺寸 @PageIndex INT=1,    --頁(yè)碼 @OrderType bit = 0,    --0升序,非0降序 @strWhere VARCHAR(1000)='',  --查詢條件 --@TotalCount INT OUTPUT   --返回總記錄數(shù))AS-- =============================================-- Author:  allen (liyuxin)-- Create date: 2012-03-30-- Description: 分頁(yè)存儲(chǔ)過(guò)程(支持多表連接查詢)-- Modify [1]: 2012-03-30-- =============================================BEGIN DECLARE @strSql VARCHAR(5000) --主語(yǔ)句 DECLARE @strSqlCount NVARCHAR(500)--查詢記錄總數(shù)主語(yǔ)句 DECLARE @strOrder VARCHAR(300) -- 排序類型 --------------總記錄數(shù)--------------- 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 --------------分頁(yè)------------ 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 @TotalCountEND
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, DbType, 0, ParameterDirection.Output, null);  }  public static SqlParameter MakeParam(string ParamName, SqlDbType DbType, Int32 Size, ParameterDirection Direction, object Value)  {   SqlParameter param;   if (Size > 0)    param = new SqlParameter(ParamName, DbType, Size);   else    param = new SqlParameter(ParamName, DbType);   param.Direction = Direction;   if (!(Direction == ParameterDirection.Output && Value == null))    param.Value = Value;   return param;  }  /// <summary>  /// 分頁(yè)獲取數(shù)據(jù)列表及總行數(shù)  /// </summary>  /// <param name="tbName">表名</param>  /// <param name="tbGetFields">返回字段</param>  /// <param name="OrderFldName">排序的字段名</param>  /// <param name="PageSize">頁(yè)尺寸</param>  /// <param name="PageIndex">頁(yè)碼</param>  /// <param name="OrderType">false升序,true降序</param>  /// <param name="strWhere">查詢條件</param>  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",SqlDbType.VarChar,1000,tbGetFields),       MakeInParam("@OrderfldName",SqlDbType.VarChar,255,OrderFldName),       MakeInParam("@PageSize",SqlDbType.Int,0,PageSize),       MakeInParam("@PageIndex",SqlDbType.Int,0,PageIndex),       MakeInParam("@OrderType",SqlDbType.Bit,0,OrderType),       MakeInParam("@strWhere",SqlDbType.VarChar,1000,strWhere),      // MakeOutParam("@TotalCount",SqlDbType.Int)      };   return RunProcedure("Proc_SqlPageByRownumber", parameters, "ds");  }

調(diào)用:

public DataTable GetList(string tbName, string tbGetFields, string OrderFldName, int PageSize, int PageIndex, 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];  }

注意:多表連接時(shí)需注意的地方

1.必填項(xiàng):tbName,OrderfldName,tbGetFields

2.實(shí)例:

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:每個(gè)條件前必須添加 AND (例如:AND UserInfo.DepID=1 )

Max/top:(簡(jiǎn)單寫了下,需要滿足主鍵字段名稱就是"id")

create proc [dbo].[spSqlPageByMaxTop]@tbName varchar(255),  --表名@tbFields varchar(1000),  --返回字段@PageSize int,    --頁(yè)尺寸@PageIndex int,    --頁(yè)碼@strWhere varchar(1000), --查詢條件@StrOrder varchar(255), --排序條件@Total int output   --返回總記錄數(shù)asdeclare @strSql varchar(5000) --主語(yǔ)句declare @strSqlCount nvarchar(500)--查詢記錄總數(shù)主語(yǔ)句--------------總記錄數(shù)---------------if @strWhere !=''beginset @strSqlCount='Select @TotalCout=count(*) from ' + @tbName + ' where '+ @strWhereendelsebeginset @strSqlCount='Select @TotalCout=count(*) from ' + @tbNameend--------------分頁(yè)------------if @PageIndex <= 0begin set @PageIndex = 1endset @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,N'@TotalCout int output',@Total outputexec(@strSql)

調(diào)用:

declare @count int--exec [dbo].[spSqlPageByRownumber]'pagetest','*',50,20,'','order by id asc',@count outputexec [dbo].[spSqlPageByMaxTop]'pagetest','*',50,20,'','order by id asc',@count outputselect @count

上述內(nèi)容就是sql中怎么實(shí)現(xiàn)分頁(yè)查詢,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

sql
AI