Web应用经常会出现分页显示结果集的场景,如果处理不好将会严重影响应用程序的性能。如何突破这个瓶颈呢?
通过一个需求演示场景给大家展示两种实现方法,孰优孰劣看后便知。
1.创建实验表T,并初始化一些实验数据
sec@ora10g> create table t (id number, sal number);
sec@ora10g> insert into t values (1,1000);
sec@ora10g> insert into t values (2,800);
sec@ora10g> insert into t values (3,600);
sec@ora10g> insert into t values (4,2000);
sec@ora10g> insert into t values (5,3000);
sec@ora10g> insert into t values (6,1500);
sec@ora10g> insert into t values (7,1800);
sec@ora10g> insert into t values (8,2100);
sec@ora10g> insert into t values (9,400);
sec@ora10g> insert into t values (10,600);
sec@ora10g> insert into t values (11,200);
sec@ora10g> insert into t values (12,1900);
sec@ora10g> insert into t values (13,3000);
sec@ora10g> insert into t values (14,4000);
sec@ora10g> commit;
2.T表数据概览
sec@ora10g> select * from t;
ID SAL
---------- ----------
1 1000
2 800
3 600
4 2000
5 3000
6 1500
7 1800
8 2100
9 400
10 600
11 200
12 1900
13 3000
14 4000
14 rows selected.
3.实现需求一:按照工资升序排序后的第1名到第3名信息
1)错误方法
sec@ora10g> select * from t where rownum<=3 order by sal;
ID SAL
---------- ----------
3 600
2 800
1 1000
这种查询方法是先获得T表中的前三条记录,然后对这三条记录的sal值进行排序。与我们的需求不符。
2)正确方法一
使用子查询与rownum完成任务。
sec@ora10g> select * from (select * from t order by sal) where rownum<=3;
ID SAL
---------- ----------
11 200
9 400
3 600
3)正确方法二
使用分析函数ROW_NUMBER完成此任务。
sec@ora10g> select id, sal
2 from (select id, sal, ROW_NUMBER () over (order by sal) as rn
3 from t)
4 where rn <= 3;
ID SAL
---------- ----------
11 200
9 400
3 600
4.实现需求二:按照工资升序排序后的第4名到第6名信息
1)错误的方法
sec@ora10g> select * from (select * from t order by sal) where rownum between 4 and 6;
no rows selected
rownum的这种使用方法是不正确的!要坚决抵制。
2)正确方法一
用rownum来构造这个结果集
sec@ora10g> select *
2 from (select * from (select * from t order by sal)
3 where ROWNUM <= 6
4 minus
5 select * from (select * from t order by sal)
6 where ROWNUM <= 3)
7 order by sal;
ID SAL
---------- ----------
10 600
2 800
1 1000
可见,使用这种集合减构造出来的结果集的方法稍显笨重。
3)正确方法二
使用分析函数ROW_NUMBER可以很便捷的完成这个任务。
sec@ora10g> select id, sal
2 from (select id, sal, ROW_NUMBER () over (order by sal) as rn
3 from t)
4 where rn between 4 and 6;
ID SAL
---------- ----------
10 600
2 800
1 1000
5.以此类推,便可以实现任意指定范围内的统计数据查询。
6.小结
“正确方法一”给出的方法虽然可以实现我们的需求,但是获取数据的代价较大,其间存在大量的排序操作。
“正确方法二”使用分析函数先对第一种方法效率上得到了保证,同时给SQL的编写带来很大的灵活性,推荐使用。
通过这个例子我们再一次体会到了分析函数带给我们的便利和高效。
Good luck.
secooler
10.02.06
-- The End --