参考文章:分页写法小结

推荐使用row_number over()方法,或2012以上使用offset

PageSize =
PageNumber =
方法一:(最常用的分页代码, top / not in)
  select top UserId from UserInfo where UserId not in (select top UserId from UserInfo order by UserId) order by UserId
备注: 注意前后的order by 一致
方法二:(not exists, not in 的另一种写法而已)
  select top * from UserLog where not exists (select from (select top LogId from UserLog order by LogId) a where a.LogId = UserLog.LogId) order by LogId
备注:EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False。此处的 select from 也可以是select from,select LogId from, select * from 等等,不影响查询。而且select 效率最高,不用查字典表。效率值比较: > anycol > *
方法三:(top / max, 局限于使用可比较列排序的时候)
  select top * from UserLog where LogId > (select max(LogId) from (select top LogId from UserLog order by LogId) a ) order by LogId
备注:这里max()函数也可以用于文本列,文本列的比较会根据字母顺序排列,数字 < 字母(无视大小写) < 中文字符
方法四:(row_number() over (order by LogId))
  select top * from ( select row_number() over (order by LogId) as rownumber,* from UserLog)awhere rownumber > order by LogId
  select * from (select row_number()over(order by LogId) as rownumber,* from UserLog)awhere rownumber > and rownumber < order by LogId
  select * from (select row_number()over(order by LogId) as rownumber,* from UserLog)awhere rownumber between and order by LogId
  select *from ( select row_number()over(order by tempColumn)rownumber,* from (select top tempColumn=,* from UserLog where = order by LogId)a)bwhere rownumber>

今天无聊和朋友讨论分页,发现网上好多都是错的。网上经常查到的那个Top Not in 或者Max 大部分都不实用,很多都忽略了Order和性能问题。为此上网查了查,顺带把2000和2012版本的也补上了。

先说说网上常见SQL的错误或者说局限问题

1
2
3
4
5
select top 10 *
from table1
where id not in(
    select top 开始的位置 id
    from table1)

这样的确是可以取到分页数据,但是这是默认排序的,如果要按其中一列排序呢?那order by 加在哪里呢?里外都加,显然不行,外面的Order不起作用,只能嵌套,Oh my god,编程三个Select了,这效率。

为了好用效率高,总体思路还是老老实实的用RowNumber解决,但是SQL2000没有RowNumber,其实我们可以通过临时表自增列搞定,不多说,上例子。

SQL 2000 用临时表解决,通过在临时表中增加自增列解决RowNumber。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 14000,@End = 14050
 
 
CREATE TABLE #employees (RowNumber INT IDENTITY(1,1),
LastName VARCHAR(100),FirstName VARCHAR(100),
EmailAddress VARCHAR(100))
 
 
INSERT INTO #employees (LastName, FirstName, EmailAddress)
SELECT LastName, FirstName, EmailAddress
FROM Employee
ORDER BY LastName, FirstName, EmailAddress
SELECT LastName, FirstName, EmailAddress
FROM #employees
WHERE RowNumber > @Start AND RowNumber <= @End
 
 
DROP TABLE #employees
 
 
GO

  

SQL 2005/2008 由于支持了Row_Number于是通过派生表的方式解决(两个嵌套)

1
2
3
4
5
6
7
8
9
10
11
12
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 14000,@End = 14050
 
 
SELECT LastName, FirstName, EmailAddress
FROM (SELECT LastName, FirstName, EmailAddress,
ROW_NUMBER() OVER (ORDER BY LastName, FirstName, EmailAddress) AS RowNumber
FROM Employee) EmployeePage
WHERE RowNumber > @Start AND RowNumber <= @End
ORDER BY LastName, FirstName, EmailAddress
GO

  

SQL 2005/2008 或者用CTE的方式实现,和派生表一样,就是好看点,执行计划都一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DECLARE @Start INT
DECLARE @End INT
SELECT @Start = 14000,@End = 14050;
 
 
WITH EmployeePage AS
(SELECT LastName, FirstName, EmailAddress,
ROW_NUMBER() OVER (ORDER BY LastName, FirstName, EmailAddress) AS RowNumber
FROM Employee)
SELECT LastName, FirstName, EmailAddress
FROM EmployeePage
WHERE RowNumber > @Start AND RowNumber <= @End
ORDER BY LastName, FirstName, EmailAddress
GO

ROW_NUMBER 比较好用的办法

--(1)在ROW_NUMBER的同时用COUNT计算总行数
declare @page_no int
declare @page_size int set @page_no = 2
set @page_size = 10 ;WITH tmp
AS
(
select *,
ROW_NUMBER() OVER(order by ID) num,
COUNT(*) OVER() total
from split_pages
)
select ID, Name
from tmp
where num BETWEEN (@page_size*(@page_no-1)+1) AND @page_size*@page_no
order by num --(2)仅使用ROW_NUMBER计算总行数,IO最少
declare @page_no int
declare @page_size int set @page_no = 2
set @page_size = 10 ;with tmp
as
(
select *,
ROW_NUMBER() OVER(order by ID) num,
ROW_NUMBER() OVER(order by ID desc) num_desc
from split_pages
)
select ID, Name, num_desc + num -1 as total
from tmp
where num BETWEEN (@page_size*(@page_no-1)+1) AND @page_size*@page_no
order by num

SQL SERVER 2012 比较给力支持了OFFSET,于是一个Select结束战斗

1
2
3
4
5
SELECT LastName, FirstName, EmailAddress
FROM Employee
ORDER BY LastName, FirstName, EmailAddress
OFFSET 14000 ROWS
FETCH NEXT 50 ROWS ONLY;

  

最后说下,根据老外的文章,在2012里,如果前面加上TOP(50),那么执行计划就会少读很多行数据(读的精准了),提高性能。但是鉴于本人手头没2012也无法测试。至少在2008R2上加不加TOP执行计划都一样。

转自:https://www.cnblogs.com/ebread/p/SQLServer.html

(3.15)常用知识-sql server分页的更多相关文章

  1. SQL Server游标 C# DataTable.Select() 筛选数据 什么是SQL游标? SQL Server数据类型转换方法 LinQ是什么? SQL Server 分页方法汇总

    SQL Server游标   转载自:http://www.cnblogs.com/knowledgesea/p/3699851.html. 什么是游标 结果集,结果集就是select查询之后返回的所 ...

  2. 解决hibernate对Sql Server分页慢的问题

    一.hibernate分页 hibernate对MsSql的伪分页 分页是web项目中比不可少的一个功能,数据量大的时候不能全部展示必然要用到分页技术.相信大家对hibernate中的分页都不陌生: ...

  3. SQL SERVER 分页方法

    最近项目中需要在SQL SERVER中进行分页,需要编写分页查询语句.之前也写过一些关于分页查询的语句,但是性能不敢恭维.于是在业务时间,在微软社区Bing了一篇老外写的关于SQL SERVER分页的 ...

  4. SQL Server分页模板

    SQL Server分页模板 WITH T AS ( SELECT ROW_NUMBER() OVER(ORDER BY AlbumId ) AS row_number, * FROM (SELECT ...

  5. SQL Server分页语句ROW_NUMBER,读取第4页数据,每页10条

    SQL Server分页语句ROW_NUMBER,读取第4页数据,每页10条 SELECT Id,[Title],[Content],[Image] FROM ( SELECT ROW_NUMBER( ...

  6. SQL server分页的四种方法

    SQL server分页的四种方法 1.三重循环: 2.利用max(主键); 3.利用row_number关键字: 4.offset/fetch next关键字 方法一:三重循环思路  先取前20页, ...

  7. 二、SQL Server 分页

    一.SQL Server 分页 --top not in方式 select top 条数 * from tablename where Id not in (select top 条数*页数 Id f ...

  8. SQL server分页的四种方法(算很全面了)

      这篇博客讲的是SQL server的分页方法,用的SQL server 2012版本.下面都用pageIndex表示页数,pageSize表示一页包含的记录.并且下面涉及到具体例子的,设定查询第2 ...

  9. SQL Server 分页方法汇总

    PageSize = 30 PageNumber = 201 方法一:(最常用的分页代码, top / not in) UserId UserId from UserInfo order by Use ...

随机推荐

  1. error: No implicit Ordering defined for Any

    scala中经常遇到最头疼的问题,就是类型不匹配或者带Any,Option的提示错误信息. 最近碰到的是取最大值,但是明明已经Long类型的,却提示下面这个错误信息. 相关的源程序如下: // 获取o ...

  2. zabbix监控数据库

    Zabbix通过percona监控MySQL   因为Zabbix自带的MySQL监控没有提供可以直接使用的Key,所以一般不采用,业界的同学们都使用Percona Monitoring Plugin ...

  3. EF应用一:Code First模式

    EF的核心程序集位于System.Data.Entity.dll和System.Data.EntityFramework.dll中.支持CodeFirst的位于EntityFramework.dll中 ...

  4. 性能加速 - 开启opcache

    说明 PHP 5.5+版本以上的,可以使用PHP自带的opcache开启性能加速(默认是关闭的).对于PHP 5.5以下版本的,需要使用APC加速,这里不说明,可以自行上网搜索PHP APC加速的方法 ...

  5. 数学 + 带权中位数 - SGU 114 Telecasting station

    Telecasting station Problem's Link Mean: 百慕大的每一座城市都坐落在一维直线上,这个国家的政府决定建造一个新的广播电视台. 经过了许多次试验后,百慕大的科学家们 ...

  6. 举例说明:Hadoop vs. NoSql vs. Sql vs. NewSql

    转自:http://blog.jobbole.com/86269/   尽管层次数据库如今在大型机上依然被广泛使用,但关系数据库(RDBMS)(SQL)已经占领了数据库市场,并且表现的相当优异.我们存 ...

  7. MapReduce的InputFormat过程的学习

    转自:http://blog.csdn.net/androidlushangderen/article/details/41114259 昨天经过几个小时的学习,把MapReduce的第一个阶段的过程 ...

  8. Spring Framework 官方文档学习(二)之IoC容器与bean lifecycle

    到目前为止,已经看了一百页.再次感慨下,如果想使用Spring,那可以看视频或者找例子,但如果想深入理解Spring,最好还是看官方文档. 原计划是把一些基本接口的功能.层次以及彼此的关系罗列一下.同 ...

  9. bootstrap基础学习三篇

    bootstrap的排版 1.标题 Bootstrap 中定义了所有的 HTML 标题(h1 到 h6)的样式 2.代码如下: <div class="container"& ...

  10. Spring中bean的作用范围

    singleton作用域: Spring的scope的默认值是singleton Spring 只会为每一个bean创建一个实例,并保持bean的引用. <bean id="bean的 ...