Oracle数据库中提取表首尾各3条记录的查询问题
解决Oracle取employee_src表前3和后3条记录的问题
嘿,我瞅出你这查询的问题了——前3条能正常拿到,但后3条的逻辑根本不对!你子查询里写的order by rownum desc完全没起到“取最后3条”的作用,因为Oracle的rownum是在生成结果集的时候逐行分配的,你还没对表的记录做真正排序,就按rownum倒序,最后拿到的只是随机几条rownum大的记录,根本不是表的最后3条。
先说说原查询的坑
你的原查询后半段:
select fname,lname,ssn,salary,dno from (select fname,lname,ssn,salary,dno from employee_src order by rownum desc) where rownum <=3这里的子查询
order by rownum desc是无效的——rownum是Oracle读取数据时就分配的,你没先对表的记录按业务逻辑排序,直接倒序rownum,相当于把“随机分配的序号”倒过来,结果自然不对。
正确的写法分两种情况
方法1:用明确的业务排序字段(强烈推荐)
如果你的表有可以用来确定顺序的字段(比如主键ssn、工资salary、入职日期这类),用它来排序是最可靠的,因为表的物理存储顺序可能会变,而业务字段的排序逻辑是固定的。
如果你用的是Oracle 12c及以上版本(支持FETCH FIRST语法)
-- 取前3条(这里按ssn升序,你可以换成你需要的排序字段,比如salary、hire_date) SELECT fname, lname, ssn, salary, dno FROM employee_src ORDER BY ssn ASC FETCH FIRST 3 ROWS ONLY UNION ALL -- 取后3条(先按ssn降序取前3,如果你想保持原顺序,可以再嵌套一层排序) SELECT fname, lname, ssn, salary, dno FROM ( SELECT fname, lname, ssn, salary, dno FROM employee_src ORDER BY ssn DESC ) FETCH FIRST 3 ROWS ONLY;
如果你用的是Oracle 11g及以下版本(只能用rownum)
-- 前3条:先排序再取rownum SELECT fname, lname, ssn, salary, dno FROM ( SELECT fname, lname, ssn, salary, dno FROM employee_src ORDER BY ssn ASC ) WHERE rownum <= 3 UNION ALL -- 后3条:先按倒序排序,再取rownum SELECT fname, lname, ssn, salary, dno FROM ( SELECT fname, lname, ssn, salary, dno FROM employee_src ORDER BY ssn DESC ) WHERE rownum <= 3;
方法2:没有业务排序字段时,用rowid(仅临时应急用)
如果实在没有合适的排序字段,只能依赖表的物理存储顺序,可以用rowid,但要注意:当表做过碎片整理、数据迁移或者批量更新后,rowid对应的顺序可能会变化,所以这不是长期可靠的方案。
-- 前3条 SELECT fname, lname, ssn, salary, dno FROM employee_src WHERE rownum <= 3 UNION ALL -- 后3条:按rowid倒序取前3 SELECT fname, lname, ssn, salary, dno FROM ( SELECT fname, lname, ssn, salary, dno FROM employee_src ORDER BY rowid DESC ) WHERE rownum <= 3;
补充说明
不管用哪种方法,核心都是:要先对整个表的记录按你需要的规则排序,再取前/后N条,而不是先分配rownum再排序——这是Oracle rownum的特性,很多新手都会踩这个坑。
内容的提问来源于stack exchange,提问作者general46
相关产品推荐
相关产品推荐

