Thanks for the question, E.J..
Asked: May 26, 2000 - 1:57 pm UTC
Last updated: May 26, 2000 - 1:57 pm UTC
Version: 7.3.4.2
Viewed 10K+ times! This question is
You Asked
In Oracle 8.0.x and earlier you can't order subselects/views so how can I return the first row of an ordered resultset without using a temp table or cursor? Here's the basic query:
select * from table order by cola, colb;
Adding the 'where rownum = 1' obviously doesn't work since it orders it after the resultset is returned.
Thanks,
E.J. Wilburn
and Tom said...
What will usually work is "group by" but you must be aware of many things:
o group by does not have to sort. In 7.3 it almost always does but as the versions go on, it does not. Partitioning, Index Organized tables, better optimizer, and so on make this the case.
o group by does a binary sort, if you are using NLS this might result in data being ordered differently then if you use an order by.
It might look like this:
select *
from ( select c1, c2, c3, cola, colb
from T
group by cola, colb, c1, c2, c3 )
where rownum = 1;
If in fact, cola+colb is unique, you can:
select *
from ( select min(c1), min(c2), min(c3), cola, colb
from T
group by cola, colb )
where rownum = 1;
for example:
1 select *
2 from ( select ename, min(empno), min(deptno)
3 from emp
4 group by ename )
5* where rownum = 1
ask_tom@OSI1.WORLD> /
ENAME MIN(EMPNO) MIN(DEPTNO)
---------- ---------- -----------
ADAMS 7876 20
1 row selected.
So, just to make sure I've caveated this -- make sure to test this on your data if you use a group by (and to convert it when you goto 8i). Here is an example of a group by that does not sort the way you expect:
SQL> create table emp as select * from scott.emp where rownum <= 5;
Table created.
SQL> create index emp_idx on emp(job,ename);
Index created.
SQL> select ename, job from emp where ename >chr(0) and job >chr(0)
2 group by ename, job ;
ENAME JOB
---------- ---------
smith CLERK
jones MANAGER
allen SALESMAN
martin SALESMAN
ward SALESMAN
Since group by ename, job is the same as group by job, ename -- it just used the index to do the work here and blew off the sort -- so beware.
Another option that always works would be:
ask_tom@OSI1.WORLD> select ename, empno, deptno
2 from emp a
3 where ename = ( select min(ename)
4 from emp )
5 and deptno = ( select min(deptno)
6 from emp b
7 where b.ename = a.ename )
8 and rownum = 1
9 /
ENAME EMPNO DEPTNO
---------- ---------- ----------
ADAMS 7876 20
1 row selected.
Where ename represents COLA and deptno represents COLB. We find the smallest (or largest) ename and for that ename we find the smallest deptno for that ename. We find the first row having that smallest ename, deptno.
Is this answer out of date? If it is, please let us know via a Comment