SQL Server 2005用Row_Number分页

1、为什么要使用row方案:
在oracle里有row_number虚列,
mySql有limit关键字分页,
他们都有一个比较通用的分页方案,
使得hibernate等类似的程序可以拼接sql字符串提供通用的分页。
而sqlserver却没有这样的分页方案。
于是乎,本人稍稍改装row_number()over(order by )用法,获得了一个通用的分页方案。
如提供了sql如下:

select * from Student where Age>18 order by Age

被row方案的分页程序处理后变成
(在select 后面添加 top 开始位置 0 __tc,在外层嵌套固定模式的查询sql)

select  * 
from (
select row_number()over(orderby __tc__)__rn__,*
from (selecttop 开始位置+100 __tc__,*from Student where Age>18 order by Age)t
)tt
where __rn__>开始位置


这样就得到了拼接出通用的分页sql方案了。
并且经过本人测试发现,这套方案的运行速度不逊于任何一套其他方案。
其余各方面效率还有待考察,忘高人指点了。

2、row方案的排序:
row方案可以任意排序,
只要修改最内层的select排序即可,
应该来说是很简单易用的。
参考【追加说明1、】和【#80楼】。

3、row方案和普通row_number()方案的区别:

一般的row方案:

select * 
from (select top 开始位置+10 row_number() over(order by Id)__rn__, * from Student)t
where __rn__>=开始的位置


使用了over(order by 表中的列),照成了必须由用户提供这个列,
而不容易使用分页程序生成分页sql(如hibernate分页)。
而row方案使用的是一个常数列tempColumn,值永远是0。

select * 
from (
select row_number() over(order by TempColmun) *
from (
select top 开始的位置 0 as TempColmun,*
from Student order by Id
)tt)t
where rowNumber >=开始的位置


这个列是静态的,只是为了使用row_number()函数,
并不是真正的order by 依据,order by 实际看最内层。

我分析是因为row方案使用一个静态的列tempColumn,
这样可能被sql分析程序认为是无需排序的,省下了排序过程的开销。

4、数据测试:
现只在我一台机子上试过,
希望路过的各位随手帮忙测试一下。
这也是我迟迟不结贴的缘故。

举手之劳,复制sql运行即可:

--插入测试数据200w条,可能会很久
create table Student(
Id int PRIMARYKEY identity(1,1),
Name nvarchar(50),
Age int)
insert Student(Name,Age)values('Name',18)
while (select count(*) from Student)<2000000
insert Student select Name,Age from Student



运行测试代码:

--开始测试查询
declare @now datetime
--max方案
select 'max' 方案
select @now=getdate()
--begin
select top 10 * from Student
where Id>(
select max(Id)
from (
select top 1999990 Id from Student order by Id)tt)
--end
declare @maxDiff int
select maxDiff=datediff(ms,@now,getdate())

--top方案
select 'top' 方案
select @now=getdate()
--begin
select top 10 * from Student
where Id not in(select top 1999990 Id from Student)
--end
declare @topDiff int
select @topDiff=datediff(ms,@now,getdate())

--row方案
select 'row' 方案
select @now=getdate()
--begin
select *
from (
select row_number()over(orderby tc)rn,*
from (select top 20000000 tc,* from Student)t
)tt
where rn>1999990
--end
declare @rowDiff int
select @rowDiff=datediff(ms,@now,getdate())

--row_number方案
select 'row_number' 方案
select @now=getdate()
--begin
select *
from(
select top2000000 row_number() over(order by Id)rn,* from Student
)t
where rn>1999990
--end
declare @row_numberDiff int
select @row_numberDiff=datediff(ms,@now,getdate())

--记录结果
select '第20万页' 页码,@maxDiff max方案,@topDiff top方案,@rowDiff row方案,@row_numberDiff row_number方案


-----------------------------------------------------------
以下为原帖:
-----------------------------------------------------------
这套方案(下面简称row方案)是本人借鉴Oracle的row_number分页方法和sqlServerrow_number结合+上top分页方案合体版,经过本人初步测试。
效率非常快。(本人测试非常业余,还望高人帮忙测试。)
row方案的具体操作方法在这章帖子里:
一套原创的sqlserver通用分页方案 忘高人测试效率 先阿里嘎多了

比较了3种分页方式,分别是max方案,top方案,row方案

效率:
  第1:row
  第2:max
  第3:top

缺点:
  max:必须用户编写复杂Sql,不支持非唯一列排序
  top:必须用户编写复杂Sql,不支持复合主键
  row:不支持sqlServer2000

测试数据:
共320万条数据,每页显示10条数据,分别测试了2万页、15万页和32万页。

页码,top方案,max方案,row方案
2万,60ms,46ms,33ms
15万,453ms,343ms,310ms
32万,953ms,720ms,686ms


具体操作sql代码如下:

top方案:

select top 10 * from Table1
where Id not in(select top 开始的位置 Id from Table1)


max:

select top 10 * from Table1
where Id>(select max(Id)
from (select top 开始位置 Id from Table1 order by Id)tt)

row:

select*
from (
select row_number() over(order by tempColumn) tempRowNumber,*
from (select top 开始位置+10 tempColumn=0,* from Table1)t
)tt
where tempRowNumber>开始位置


参考:http://topic.csdn.net/u/20100617/04/80d1bd99-2e1c-4083-ad87-72bf706cb536.html




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在SQL Server,可以使用ROW_NUMBER()函数进行分页查询。ROW_NUMBER()函数会为结果集的每一行分配一个唯一的数字,该数字从1开始依次递增。我们可以利用这个函数来实现分页查询。 下面是一个例子: 假设我们有一个名为"employees"的表,其包含员工的姓名和工资信息。我们想要查询前10个工资最高的员工,并按照工资降序排列。 我们可以使用如下的SQL语句来实现: ``` SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY salary DESC) AS rownum, * FROM employees ) AS temp WHERE rownum BETWEEN 1 AND 10 ``` 上述SQL语句ROW_NUMBER()函数被用来为每一行分配一个数字,按照工资降序排列。然后,我们将该子查询嵌套在一个外部查询,并利用WHERE子句来选择第1到第10行,从而实现了分页查询。 ### 回答2: 在SQL Server,可以使用ROW_NUMBER函数进行分页查询。ROW_NUMBER函数是一种窗口函数,它可以为查询结果的每一行分配一个唯一的行号。 以下是使用ROW_NUMBER进行分页查询的基本语法: ``` SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY column) AS RowNum FROM table ) AS SubQuery WHERE RowNum BETWEEN @startRow AND @endRow ``` 在上述语法,`column`是用于排序的列名,`table`是要查询的表名,`@startRow`和`@endRow`是指定的分页起始行和结束行。 首先,ROW_NUMBER函数被应用于子查询,它会为每一行生成一个行号。`ORDER BY`子句用于确定行号的顺序。 然后,在外部查询,我们可以使用`WHERE`子句来过滤我们想要的行号范围。 例如,如果我们想要查询第1行到第10行的数据,我们可以将`@startRow`设置为1,`@endRow`设置为10。 需要注意的是,ROW_NUMBER是基于查询结果集的顺序生成行号,而不是基于表的物理顺序。因此,如果没有明确指定`ORDER BY`子句,结果可能是不确定的。 使用ROW_NUMBER函数进行分页查询能够有效地提取出我们所需的数据,并且还可以通过调整`@startRow`和`@endRow`的值来获取不同的分页结果。 ### 回答3: 在SQL Server,可以使用ROW_NUMBER()函数来实现分页查询。ROW_NUMBER()函数会按照指定的排序规则对结果集进行排序,并为每一行赋予一个序号。通过指定分页起始位置和每页的行数,可以得到想要的分页结果。 例如,假设有一个名为"Products"的表,我们需要按照价格降序排列并进行分页查询,每页显示10条记录。可以使用以下SQL语句实现: ```sql SELECT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY Price DESC) AS RowNum, * FROM Products ) AS P WHERE RowNum BETWEEN 1 AND 10 ``` 在这个查询,使用ROW_NUMBER()函数为结果集的每一行赋予一个序号,并按照价格降序进行排序。然后在外部查询,通过WHERE子句指定了分页的起始位置和每页的行数,这里的起始位置为1,结束位置为10,表示获取第1页的数据,每页10条记录。 通过这种方式,可以方便地实现分页查询。在实际应用,可以根据需要调整分页起始位置和每页的行数,以实现更复杂的分页需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值