工作中遇到问题:分页查询两个页面查询的数据一样,
select *
from
(
select rownum as rw,a1.*
from (
.....................
)
order by mdi.createdate desc
) a1
where rownum<=30
) m
where rw>=16
查网后发现:
测试:
表结构及数据如下:
create table my_test
(
ID NUMBER(10) not null,
TYPE NUMBER(1) not null,
NAME VARCHAR2(50) not null
);
insert into my_test (ID, TYPE, NAME) values (1, 0, 'A');
insert into my_test (ID, TYPE, NAME) values (2, 1, 'B');
insert into my_test (ID, TYPE, NAME) values (3, 1, 'C');
insert into my_test (ID, TYPE, NAME) values (4, 0, 'D');
insert into my_test (ID, TYPE, NAME) values (5, 0, 'E');
insert into my_test (ID, TYPE, NAME) values (6, 1, 'F');
insert into my_test (ID, TYPE, NAME) values (7, 0, 'G');
insert into my_test (ID, TYPE, NAME) values (8, 1, 'H');
insert into my_test (ID, TYPE, NAME) values (9, 1, 'I');
insert into my_test (ID, TYPE, NAME) values (10, 0, 'J');
commit;
我的SQL查询语句为:
select * from my_test order by TYPE ASC
结果显示为
1 0 A
5 0 E
7 0 G
10 0 J
4 0 D
6 1 F
8 1 H
9 1 I
3 1 C
2 1 B
如果我只想取出前4条记录,使用如下SQL:
select tbl.* from (select * from my_test order by TYPE ASC) tbl where rownum <= 4
根据前面查询的结果,数据应该是
1 0 A
5 0 E
7 0 G
10 0 J
但是实际上确不是这样:
1 0 A
4 0 D
5 0 E
7 0 G
并且,如果我设定 rownum <= 5,结果又有所不同
select tbl.* from (select * from my_test order by TYPE ASC) tbl where rownum <= 5
1 0 A
4 0 D
5 0 E
10 0 J
7 0 G
ID为10的记录跑到ID为7的记录前面了。
换句话说,结果集由于rownum限制不同而改变了排列顺序。
只要 order by 子句中的字段不能唯一确定查询结果的顺序时,使用rownum 限制记录数量会造成排序混乱的问题。
这个问题会使数据在分页显示时无法正确进行,不同页面间显示的数据可能会包含同一条记录。
解决办法就是在order by 子句中再增加一个可以唯一确定顺序的字段(例如 order by TYPE ASC, ID ASC)