我正在使用Oracle数据库。
在我的查询中,提取了100行。如果我想在rownum 50和60之间过滤行,那么查询是什么?
SELECT EMPLID, EFFDT, ACTION, ACTION_REASON
from JOB where emplid ='12345'
答案 0 :(得分:8)
大多数人通常会告诉你使用ROWNUM来做这件事,但更简洁的方法是使用row_number()分析函数。
select EMPLID, EFFDT, ACTION, ACTION_REASON
from
(
SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn
from JOB where emplid ='12345'
)
where rn between 50 and 60;
使用row_number函数可以在单个查询中对结果进行排序和编号,然后只需要一个包装器查询来获取所需的行。
答案 1 :(得分:8)
由于我对Chad's和Nick's方法进行了比较,以便对Nick的回答发表评论,我想我会在此发布我的发现。我使用了Tom Kyte的runstats包来比较它们:
begin
runstats_pkg.rs_start('Chad');
for i in 1..10000 loop
for r in (
SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON
FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
FROM JOB
WHERE emplid = '12345')
WHERE rownum <= 60
)
WHERE rnum >= 50
) loop
null;
end loop;
end loop;
runstats_pkg.rs_middle('Nick');
for i in 1..10000 loop
for r in (
select EMPLID, EFFDT, ACTION, ACTION_REASON
from
(
SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn
from JOB where emplid ='12345'
)
where rn between 50 and 60
) loop
null;
end loop;
end loop;
runstats_pkg.rs_stop(0,false,false,false,false,false,false,false,false);
end;
/
结果:
Run1 = Chad
Run2 = Nick
*** Comparative Time Report ***
Run Time (hsecs)
--------------------------------------------------
Run1 69
Run2 77
Run1 ran in 89.61% of the time of Run2
Run2 ran in 111.59% of the time of Run1
PL/SQL procedure successfully completed.
使用autotrace可以看出计划非常相似:
SQL> SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
2 FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON
3 FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
4 FROM JOB
5 WHERE emplid = '12345')
6 WHERE rownum <= 60
7 )
8 WHERE rnum >= 50
9 /
no rows selected
Execution Plan
----------------------------------------------------------
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 41 | 3 (0)|
|* 1 | VIEW | | 1 | 41 | 3 (0)|
|* 2 | COUNT STOPKEY | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| JOB | 1 | 13 | 3 (0)|
|* 4 | INDEX RANGE SCAN | JOB2_PK | 1 | | 2 (0)|
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RNUM">=50)
2 - filter(ROWNUM<=60)
4 - access("EMPLID"=12345)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
264 bytes sent via SQL*Net to client
231 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL> select EMPLID, EFFDT, ACTION, ACTION_REASON
2 from
3 (
4 SELECT EMPLID, EFFDT, ACTION, ACTION_REASON, row_number() over (order by emplid) rn
5 from JOB where emplid ='12345'
6 )
7 where rn between 50 and 60
8 /
no rows selected
Execution Plan
----------------------------------------------------------
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 41 | 3 (0)|
|* 1 | VIEW | | 1 | 41 | 3 (0)|
|* 2 | WINDOW NOSORT STOPKEY | | 1 | 17 | 3 (0)|
| 3 | TABLE ACCESS BY INDEX ROWID| JOB | 1 | 17 | 3 (0)|
|* 4 | INDEX RANGE SCAN | JOB2_PK | 1 | | 2 (0)|
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=50 AND "RN"<=60)
2 - filter(ROW_NUMBER() OVER ( ORDER BY "EMPLID")<=60)
4 - access("EMPLID"=12345)
filter("EMPLID"=12345)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
264 bytes sent via SQL*Net to client
231 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
看起来在两种方法之间没有多少选择,尽管Chad's在我的数据库上的速度一直比较快:
Oracle数据库10g 10.2.0.3.0版 - 64位生产
答案 2 :(得分:7)
在Oracle中有点棘手,我认为你必须做这样的事情:
SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
FROM (SELECT ROWNUM rnum, EMPLID,EFFDT,ACTION,ACTION_REASON
FROM (SELECT EMPLID,EFFDT,ACTION,ACTION_REASON
FROM JOB
WHERE emplid = '12345')
WHERE rownum <= 60
)
WHERE rnum >= 50;
答案 3 :(得分:0)
您可以使用ROWNUM(请参阅this link)。 如果需要控制排序顺序,可以围绕查询包装另一个查询。