(3.15)常用知识-sql server分页查询
参考文章:分页写法小结
推荐使用row_number over()方法,或2012以上使用offset
方法一:(最常用的分页代码, top / not in)
select top 30 UserId from UserInfo
where UserId not in
(
select top 6000 UserId from UserInfo order by UserId
) order by UserId -- 备注: 注意前后的order by 一致
方法二:(not exists, not in 的另一种写法而已)
select top 30 * from UserLog where not exists
(
select 1 from
(select top 6000 LogId from UserLog order by LogId) a where a.LogId = UserLog.LogId
) order by LogId
备注:EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False。
此处的 select 1 from 也可以是select 2 from,select LogId from, select * from 等等,不影响查询。而且select 1 效率最高,不用查字典表。效率值比较:1 > anycol > *
方法三:(top / max, 局限于使用可比较列排序的时候)
select top 30 * from UserLog where LogId > ( select max(LogId) from (select top 6000 LogId from UserLog order by LogId) a ) order by LogId --备注:这里max()函数也可以用于文本列,文本列的比较会根据字母顺序排列,数字 < 字母(无视大小写) < 中文字符
方法四:(row_number() over (order by LogId))
select top 30 * from ( select row_number() over (order by LogId) as rownumber,* from UserLog)awhere rownumber > 6000 order by LogId select * from (select row_number()over(order by LogId) as rownumber,* from UserLog)awhere rownumber > 6000 and rownumber < 6030 order by LogId select * from (select row_number()over(order by LogId) as rownumber,* from UserLog)awhere rownumber between 6000 and 6030 order by LogId select *from ( select row_number()over(order by tempColumn)rownumber,* from (select top 6030 tempColumn=0,* from UserLog where 1=1 order by LogId)a)bwhere rownumber>6000
【Sql server2000】分页办法推荐
(1)传统的top not in方式的弊端
今天无聊和朋友讨论分页,发现网上好多都是错的。网上经常查到的那个Top Not in 或者Max 大部分都不实用,很多都忽略了Order和性能问题。为此上网查了查,顺带把2000和2012版本的也补上了。
先说说网上常见SQL的错误或者说局限问题
select top 10 * from table1 where id not in( select top 开始的位置 id from table1)
这样的确是可以取到分页数据,但是这是默认排序的,如果要按其中一列排序呢?那order by 加在哪里呢?里外都加,显然不行,外面的Order不起作用,只能嵌套,Oh my god,编程三个Select了,这效率。
为了好用效率高,总体思路还是老老实实的用RowNumber解决,但是SQL2000没有RowNumber,其实我们可以通过临时表自增列搞定,不多说,上例子。
(2)SQL 2000 用临时表解决,通过在临时表中增加自增列解决RowNumber
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 server2005~~Sql server2008】分页办法推荐
(1)使用row_number 构建派生表
SQL 2005/2008 由于支持了Row_Number于是通过派生表的方式解决(两个嵌套)
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
(2)使用CTE+Row_number
SQL 2005/2008 或者用CTE的方式实现,和派生表一样,就是好看点,执行计划都一样。
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
(3)row_number分页实践(推荐)
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 server2012及以上】推荐分页方法
(1)offset fetch next
SQL SERVER 2012 比较给力支持了OFFSET,于是一个Select结束战斗
SELECT LastName, FirstName, EmailAddress FROM Employee ORDER BY LastName, FirstName, EmailAddress OFFSET 14000 ROWS FETCH NEXT 50 ROWS ONLY;
代码中
OFFSET 14000 ROWS
FETCH NEXT 50 ROWS ONLY;
意思是,从上述 select 结果集中,第14000行开始读取,取接下来的50行。
和mysql中的 limit m,n 一样。从第 m 行开始读取,取接下来的 n 行
最后说下,根据老外的文章,在2012里,如果前面加上TOP(50),那么执行计划就会少读很多行数据(读的精准了),提高性能。这个还没有测试过、。
参考:https://www.cnblogs.com/ebread/p/SQLServer.html
相关文章
- SQL Server-聚焦sp_executesql执行动态SQL查询性能真的比exec好?
- SQL Server-聚焦深入理解动态SQL查询(三十二)
- SQL Server-简单查询示例(十一)
- SQL Server - Management Studio - Client Statistics - Wait time on server replies vs Client processing time
- sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)
- sql server 左下角一直显示正在执行查询,应该是某个进程阻塞了
- SQL案例分析-地铁换乘线路查询.sql
- Sql Server中将Select的查询结果存入一个表!(示例)
- Sql Server 函数的操作实例!(执行多条语句,返回Select查询后的临时表)
- 本人收藏的Sql server经典t-sql语句(备忘录,持续更新中)
- SQL SERVER错误:已超过了锁请求超时时段。 (Microsoft SQL Server,错误: 1222)
- 性能测试:自建数据库与RDS性能对比SQL Server案例排查分析
- SQL Server 死锁
- sql:SQL Server metadata queries
- Sql Server 2012 分页方法分析(offset and fetch)
- SQL Server查询优化方法(查询速度慢的原因很多,常见如下几种) .
- SQL Server高速生成SQL增删改查语句
- 【bat】sql server在多台服务器上执行SQL脚本
- windows server 2012R2 如何安装 sql server2016(.net framework4.6,KB2919355)
- sql server查询行数和加了order by的查询行数不同!!!
- sql server存储引擎启动错误(SQL Server could not spawn FRunCM thread)
- (4.12)数据库列式存储 sql server列存储索引
- SQL Server跨服务器查询
- sql server 每日备份:新手遇到的问题解决方法(一)
- SQL server int 转char类型