SQL分页查询的写法,网上流传比较广的有这么三种
1.是利用Max(或者Min)函数
2.利用游标
3.利用not in
至于效率也是各有各说法,我没去实际的比较,不好妄论。恰逢今天在处理个分页。顺便记录下我的做法(其实也就是第一种,利用min函数)
先说下业务场景:
客户端请求当前数据之前的一部分数据,而这部分数据跟当前数据的关系在于时间上是连续的。在数据库中表现为:按照时间来排序的查询中,这两部分数据是前后顺序的
而这跟普通的分页不一样的地方在于:普通的分页只要关系全部数据的计算,而我这边需要有个标示来说,数据查询的起始位置。其实差异很小
CREATE PROCEDURE [dbo].[spThemeTopList] ( @page_size nvarchar(5), -- 一页记录数 @page_index nvarchar(5), -- 当前页数 @max_id nvarchar(50), -- 目前最大id @type_id nvarchar(5), -- 主题类型 @userid nvarchar(50) -- 用户id ) AS BEGIN DECLARE @WhereStr nvarchar(4000), @sqlStr nvarchar(4000) --userid 有可能为空,这边坐个判断 IF @userid<>'' BEGIN set @WhereStr = ' AND t.UserId='''+@userid+'''' END --- 首次加载数据时,[@max_id] 与 [@page_index] 都为0 则默认取 数据库最前面 [@page_size] 条 -- 'SELECT TOP '+ @page_size +' IF(@page_index=0) BEGIN set @sqlStr = 'SELECT TOP '+ @page_size+' t.ThemeId,t.ThemeTitle AS title,t.UserId,t.ThemeContent AS body, t.ThemeTime,u.UserName AS [name],u.ImagePath AS headId,t.ImagePath AS picId FROM [Theme] t LEFT JOIN [User] u ON t.UserId=u.UserId WHERE t.TypeId= ''' + @type_id +'''' + @WhereStr + ' ORDER BY t.ThemeId DESC' END ELSE BEGIN set @sqlStr = 'SELECT TOP '+ @page_size +' t.ThemeId,t.ThemeTitle AS title,t.UserId,t.ThemeContent AS body, t.ThemeTime,u.UserName AS [name],u.ImagePath AS headId,t.ImagePath AS picId FROM [Theme] t LEFT JOIN [User] u ON t.UserId=u.UserId WHERE t.TypeId= ''' + @type_id +''' AND t.ThemeId<(SELECT MIN(t3.ThemeId) FROM (SELECT TOP '+ cast((cast(@page_size as int) * cast(@page_index as int)) as nvarchar(5)) +' t2.ThemeId FROM [Theme] t2 WHERE t2.ThemeId< '''+@max_id+''' order by t2.ThemeId DESC) t3)' + @WhereStr + 'ORDER BY t.ThemeId DESC ' END END exec (@sqlStr)
另外,很吐血的是,@page_size 这个参数,竟然不能定义为int型,会报Select Top 不能从varchar转换成int型,这个错。不知道是什么原因,有空可以研究下。
所以只能定义成nvarchar,后续的计算在来转换,有点蛋疼,需要转换两次