SQL分页查询的几种方式

本文介绍了SQL Server和MySQL中实现分页查询的多种方法,包括使用TOP、BETWEEN AND、WITH子句及OFFSET-FETCH等,详细解析了各种方法的特点及适用场景。

SQL分页查询的几种方式

需求:查询表dbo.Message,每页10条,查询第2页

1:TOP()
SELECT TOP(20) * FROM  dbo.Message WHERE Code NOT IN
(SELECT TOP(10) Code FROM dbo.Message)
2:BETWEEN * AND * , Row_Number() OVER(ORDER BY *) AS rowNum
SELECT *,ROW_NUMBER() OVER(ORDER BY Code) AS rowNum INTO #a FROM  dbo.Message 
SELECT * FROM #a WHERE rowNum BETWEEN 11 AND 20
DROP TABLE #a;

或者:

SELECT * FROM (
                SELECT  *, ROW_NUMBER() OVER (ORDER BY CreateTime DESC) AS 'RowNumberForSplit'
                FROM  office.Conference 
                WHERE  1=1) temp 
WHERE RowNumberForSplit BETWEEN 1 AND 10
3:WITH * AS () , Row_Number() OVER(ORDER BY *) AS rowNum
WITH sss AS(
SELECT *,ROW_NUMBER() OVER(ORDER BY CreateTime) AS rowNum FROM DBO.Message
)
SELECT * FROM sss WHERE rowNum BETWEEN 11 AND 20
4: SQL Server 2012的OFFSET-FETCH筛选
SELECT * FROM DBO.Message ORDER BY CreateTime OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

这里第4中方法做详细介绍:

TOP选项是一个非常实用的筛选类型,但它有两个缺陷——不是标准SQL,且不支持跳过功能。标准SQL定义的TOP类似筛选称为OFFSET-FETCH,支持跳过功能,这对针对特定页面的查询非常有用。SQL Server2012引入了对OFFSET-FETCH筛选的支持。

SQL Server 2012中的OFFSET-FETCH筛选被视为ORDER BY子句的一部分,通常用于实现按顺序显示效果。OFFSET子句指定要跳过的行数,FETCH子句指定在跳过的行数后要筛选的行数。请思考一下下面的查询示例。

SELECT orderid, orderdate, custid, empid

FROM Sales.Orders

ORDER BY orderdate, orderid

OFFSET 50 ROWS FETCH NEXT 25 ROWS ONLY;

此查询按orderdate、orderid顺序(订单日期从最远到最近,并添加了决胜属性(tiebreaker)orderid)排序Orders表中的行。基于此顺序,OFFSET子句跳过前50行,由FETCH子句仅筛选下面的25行。

请注意,使用OFFSET-FETCH的查询必须具有ORDER BY子句。此外,FETCH子句不支持没有OFFSET子句。如果你不想跳过任何行,但是希望使用FETCH筛选,你应当使用OFFSET 0 ROWS来表示。不过,没有FETCH的OFFSET是允许的,这种情况是跳过指定的行数,并返回查询结果中所有剩余行。

OFFSET-FETCH语法有一些有趣的语言方面需要注意。单数格式ROW和复数格式ROWS是可以互换的,此举是让你能够以直观的类似英语方式来描述筛选。例如,假设你仅希望获取一行,如果你指定了FETCH 1 ROWS,虽然这在语法上是有效的,不过看上去会很怪。因此,你可以使用FETCH 1 ROW格式。此互换同样适用于OFFSET子句。另外,如果你不希望跳过任何行(OFFSET 0 ROWS),你可能觉得“first”比“next”更合适,因此,FIRST 和NEXT格式是可以互换的。

如你所见,从支持跳过功能看,OFFSET-FETCH子句比TOP子句更灵活。不过,OFFSET-FETCH 不支持PERCENT和WITH TIES选项,而TOP支持。由于OFFSET-FETCH是标准的,而TOP不是,我建议使用OFFSET-FETCH作为你的默认选择,除非你需要TOP支持且OFFSET-FETCH不支持的功能。


MySql数据库实现分页查询的SQL语句写法!

一:分页需求:

客户端通过传递start(页码),limit(每页显示的条数)两个参数去分页查询数据库表中的数据,那我们知道MySql数据库提供了分页的函数limit m,n,但是该函数的用法和我们的需求不一样,所以就需要我们根据实际情况去改写适合我们自己的分页语句,具体的分析如下:

比如:

查询第1条到第10条的数据的sql是:select * from table limit 0,10; ->对应我们的需求就是查询第一页的数据:select * from table limit (1-1)*10,10;

查询第10条到第20条的数据的sql是:select * from table limit 10,20; ->对应我们的需求就是查询第二页的数据:select * from table limit (2-1)*10,10;

查询第20条到第30条的数据的sql是:select * from table limit 20,30; ->对应我们的需求就是查询第三页的数据:select * from table limit (3-1)*10,10;

二:通过上面的分析,可以得出符合我们自己需求的分页sql格式是:*select from table limit (start-1)*limit,**limit; 其中start是页码,limit是每页显示的条数。

### MySQL 分页查询的方法 #### 使用 `LIMIT` 和 `OFFSET` 最常见的方式是在 SQL 查询中使用 `LIMIT` 子句配合 `OFFSET` 来实现分页。这种方式简单直观,适用于大多数情况下的分页需求。 ```sql SELECT * FROM table_name LIMIT page_size OFFSET offset_value; ``` 例如,要获取第一页的数据(假设每页显示 10 行),可以这样写: ```sql SELECT * FROM users LIMIT 10 OFFSET 0; -- 获取前 10 行 ``` 如果想要获取第二页的数据,则设置偏移量为第一个参数乘以 (当前页数减一),即 `(page_number - 1) * page_size`[^4]。 #### 利用 `SQL_CALC_FOUND_ROWS` 为了知道总共有多少条记录以便计算总的页码数目,在某些版本的 MySQL 中支持 `SQL_CALC_FOUND_ROWS` 关键字。这允许在一次查询的同时返回符合条件的结果总数。 ```sql SELECT SQL_CALC_FOUND_ROWS * FROM articles WHERE status = 'published' LIMIT 10 OFFSET 0; -- 接着通过另一个查询获得匹配行的数量 SELECT FOUND_ROWS(); ``` 不过需要注意的是自 MySQL 8.0 开始已经废弃了此特性,因此不推荐继续依赖这种方法。 #### 基于主键或唯一索引列进行分页 当面对大量数据时,传统的基于 `OFFSET` 的分页性能会逐渐下降。此时可考虑采用更高效的算法——依据表中的主键或其他唯一索引来构建查询条件,从而减少扫描范围并加快响应速度。 比如按照 ID 字段升序排列后取下一批次项目: ```sql SELECT * FROM orders WHERE id > last_seen_id ORDER BY id ASC LIMIT 10; ``` 这里的关键在于保存上次请求的最大ID值作为下次加载更多项的基础起点[^3]。 #### 多表联合 (`UNION`) 实现复杂逻辑下的分页 有时业务场景可能涉及多张表格之间的关联操作后再做分页处理。这时可以通过先分别对各个子集应用各自的过滤条件再将其结果集组合起来最后实施统一限制。 ```java String sqlPartOne = "SELECT col1, col2 FROM tbl_a WHERE ..."; String sqlPartTwo = "SELECT col1, col2 FROM tbl_b WHERE ..."; // 合并两个部分并通过 Java 执行最终带有 LIMIT 的完整语句 PreparedStatement pstmt = conn.prepareStatement(sqlPartOne + " UNION ALL (" + sqlPartTwo + ") ORDER BY some_column LIMIT ?, ?"); pstmt.setInt(1, pageNumber); pstmt.setInt(2, pageSize); ResultSet rs = pstmt.executeQuery(); ``` 上述例子展示了如何借助编程语言的能力动态拼接 SQL 并安全传递参数完成复杂的分页任务[^2]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值