MySQL学习,详解分页查询(limit)
发布于 2021-10-16 10:06
limit介绍
limit⽤来限制select查询返回的⾏数,常⽤于分页等操作。
语法:
select 列 from 表 limit [offset,] count;
说明:
offset:表⽰偏移量,通俗点讲就是跳过多少⾏,offset可以省略,默认为0,表
⽰跳过0⾏;范围:[0,+∞)。
count:跳过offset⾏之后开始取数据,取count⾏记录;范围:[0,+∞)。
limit中offset和count的值不能⽤表达式。
下⾯我们列⼀些常⽤的⽰例来加深理解。
获取前n⾏记录
select 列 from 表 limit 0,n;
或者
select 列 from 表 limit n;
⽰例,获取订单的前2条记录,如下:
mysql> create table t_order(
-> id int not null auto_increment comment '订单编号',
-> price decimal(10,2) not null default 0 comment '订单⾦额',
-> primary key(id)
-> )comment '订单表';
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t_order (price) values (88.95),(100.68),(500),
(300),(20.88),(200.5);Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from t_order;
+----+--------+
| id | price |
+----+--------+
| 1 | 88.95 |
| 2 | 100.68 |
| 3 | 500.00 |
| 4 | 300.00 |
| 5 | 20.88 |
| 6 | 200.50 |
+----+--------+
6 rows in set (0.00 sec)
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a limit 2;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 1 | 88.95 |
| 2 | 100.68 |
+--------------+--------------+
2 rows in set (0.00 sec)
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a limit 0,2;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 1 | 88.95 |
| 2 | 100.68 |
+--------------+--------------+
2 rows in set (0.00 sec)
获取最⼤的⼀条记录
我们需要获取订单⾦额最⼤的⼀条记录,可以这么做:先按照⾦额降序,然后取第⼀条记
录,如下:mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 3 | 500.00 |
| 4 | 300.00 |
| 6 | 200.50 |
| 2 | 100.68 |
| 1 | 88.95 |
| 5 | 20.88 |
+--------------+--------------+
6 rows in set (0.00 sec)
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc limit 1;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 3 | 500.00 |
+--------------+--------------+
1 row in set (0.00 sec)
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc limit 0,1;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 3 | 500.00 |
+--------------+--------------+
1 row in set (0.00 sec)
获取排名第n到m的记录
我们需要先跳过n-1条记录,然后取m-n+1条记录,如下:
select 列 from 表 limit n-1,m-n+1;如:我们想获取订单⾦额最⾼的3到5名的记录,我们需要跳过2条,然后获取3条记录,
如下:
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 3 | 500.00 |
| 4 | 300.00 |
| 6 | 200.50 |
| 2 | 100.68 |
| 1 | 88.95 |
| 5 | 20.88 |
+--------------+--------------+
6 rows in set (0.00 sec)
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc limit 2,3;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 6 | 200.50 |
| 2 | 100.68 |
| 1 | 88.95 |
+--------------+--------------+
3 rows in set (0.00 sec)
分⻚查询
开发过程中,分页我们经常使⽤,分页⼀般有2个参数:
page:表⽰第⼏页,从1开始,范围[1,+∞)
pageSize:每页显⽰多少条记录,范围[1,+∞)
如:page = 2,pageSize = 10,表⽰获取第2页10条数据。
我们使⽤limit实现分页,语法如下:select 列 from 表名 limit (page - 1) * pageSize,pageSize;
需求:我们按照订单⾦额降序,每页显⽰2条,依次获取所有订单数据、第1页、第2页、
第3页数据,如下:
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 3 | 500.00 |
| 4 | 300.00 |
| 6 | 200.50 |
| 2 | 100.68 |
| 1 | 88.95 |
| 5 | 20.88 |
+--------------+--------------+
6 rows in set (0.00 sec)
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc limit 0,2;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 3 | 500.00 |
| 4 | 300.00 |
+--------------+--------------+
2 rows in set (0.00 sec)
mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc limit 2,2;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 6 | 200.50 |
| 2 | 100.68 |
+--------------+--------------+
2 rows in set (0.00 sec)mysql> select a.id 订单编号,a.price 订单⾦额 from t_order a order by
a.price desc limit 4,2;
+--------------+--------------+
| 订单编号 | 订单⾦额 |
+--------------+--------------+
| 1 | 88.95 |
| 5 | 20.88 |
+--------------+--------------+
2 rows in set (0.00 sec)
避免踩坑
limit中不能使⽤表达式
mysql> select * from t_order where limit 1,4+1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'limit 1,4+1' at line 1
mysql> select * from t_order where limit 1+0;
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'limit 1+0' at line 1
mysql>
结论:limit后⾯只能够跟明确的数字。
limit后⾯的2个数字不能为负数
mysql> select * from t_order where limit -1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'limit -1' at line 1
mysql> select * from t_order where limit 0,-1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'limit 0,-1' at line 1
mysql> select * from t_order where limit -1,-1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right
syntax to use near 'limit -1,-1' at line 1
排序分⻚存在的坑
准备数据:
mysql> insert into test1 (b) values (1),(2),(3),(4),(2),(2),(2),(2);
Query OK, 8 rows affected (0.01 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> select * from test1;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 2 |
| 6 | 2 |
| 7 | 2 |
| 8 | 2 |
+---+---+
8 rows in set (0.00 sec)
mysql> select * from test1 order by b asc;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 2 |
| 5 | 2 |
| 6 | 2 |
| 7 | 2 |
| 8 | 2 |
| 3 | 3 |
| 4 | 4 |+---+---+
8 rows in set (0.00 sec)
下⾯我们按照b升序,每页2条数据,来获取数据。
下⾯的sql依次为第1页、第2页、第3页、第4页、第5页的数据,如下:
mysql> select * from test1 order by b asc limit 0,2;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 2 |
+---+---+
2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc limit 2,2;
+---+---+
| a | b |
+---+---+
| 8 | 2 |
| 6 | 2 |
+---+---+
2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc limit 4,2;
+---+---+
| a | b |
+---+---+
| 6 | 2 |
| 7 | 2 |
+---+---+
2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc limit 6,2;
+---+---+
| a | b |
+---+---+
| 3 | 3 |
| 4 | 4 |
+---+---+2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc limit 7,2;
+---+---+
| a | b |
+---+---+
| 4 | 4 |
+---+---+
1 row in set (0.00 sec)
上⾯有2个问题:
问题1:看⼀下第2个sql和第3个sql,分别是第2页和第3页的数据,结果出现了相同的数
据,是不是懵逼了。
问题2:整个表只有8条记录,怎么会出现第5页的数据呢,又懵逼了。
我们来分析⼀下上⾯的原因:主要是b字段存在相同的值,当排序过程中存在相同的值
时,没有其他排序规则时,mysql懵逼了,不知道怎么排序了。
就像我们上学站队⼀样,按照⾝⾼排序,那⾝⾼⼀样的时候如何排序呢?⾝⾼⼀样的就乱
排了。
建议:排序中存在相同的值时,需要再指定⼀个排序规则,通过这种排序规则不存在⼆义
性,⽐如上⾯可以再加上a降序,如下:
mysql> select * from test1 order by b asc,a desc;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 8 | 2 |
| 7 | 2 |
| 6 | 2 |
| 5 | 2 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
+---+---+8 rows in set (0.00 sec)
mysql> select * from test1 order by b asc,a desc limit 0,2;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 8 | 2 |
+---+---+
2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc,a desc limit 2,2;
+---+---+
| a | b |
+---+---+
| 7 | 2 |
| 6 | 2 |
+---+---+
2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc,a desc limit 4,2;
+---+---+
| a | b |
+---+---+
| 5 | 2 |
| 2 | 2 |
+---+---+
2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc,a desc limit 6,2;
+---+---+
| a | b |
+---+---+
| 3 | 3 |
| 4 | 4 |
+---+---+
2 rows in set (0.00 sec)
mysql> select * from test1 order by b asc,a desc limit 8,2;
Empty set (0.00 sec)看上⾯的结果,分页数据都正常了,第5页也没有数据了。
总结
• order by ... [asc|desc]⽤于对查询结果排序,asc:升序,desc:降序,asc|desc可以省
略,默认为asc
• limit⽤来限制查询结果返回的⾏数,有2个参数(offset,count),offset:表⽰跳过
多少⾏,count:表⽰跳过offset⾏之后取count⾏
• limit中offset可以省略,默认值为0
• limit中offset 和 count都必须⼤于等于0
• limit中offset和count的值不能⽤表达式
• 分页排序时,排序不要有⼆义性,⼆义性情况下可能会导致分页结果乱序,可以在后
⾯追加⼀个主键排序
本文来自网络或网友投稿,如有侵犯您的权益,请发邮件至:aisoutu@outlook.com 我们将第一时间删除。
相关素材