Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Mailing Lists -> Oracle-L -> RE: Top N query
Hi Lisa,
Here is the Code for 8i ( The script will NOT run in an earlier version as it relies on several different Oracle8i specific features )
Muthu - New Jersey
This SQL*Plus script should be run as user SCOTT (or as a user who has
access to
the EMP table) in an Oracle8i database.
REM
REM This script demonstrates how to fetch the top n occurences of column
2
REM for each distinct occurence of column 1, for example say the 2
REM highest employee numbers for each department in the emp table.
REM
REM In this example we will initially use simple numeric data to
demonstrate
REM the functionality.
REM
REM The result is achieved with the use of a nested table type - the data
REM from which we wish to take the top n records (eg empnos in the above
REM example) is cast to a nested table type then unnested again using the
REM new Oracle8i collection unnesting feature.
REM
REM
REM Create the table and data.
REM
drop table top
/
create table top (c1 number, c2 number)
/
insert into top values (1,1)
/
insert into top values (1,2)
/
insert into top values (1,3)
/
insert into top values (1,4)
/
insert into top values (1,5)
/
insert into top values (2,1)
/
insert into top values (2,2)
/
insert into top values (2,3)
/
insert into top values (2,4)
/
insert into top values (2,5)
/
insert into top values (3,1)
/
insert into top values (3,2)
/
insert into top values (3,3)
/
insert into top values (3,4)
/
insert into top values (3,5)
/
commit
/
REM
REM Fetch the top 3 column c2 values for each distinct column c1 value.
REM
REM Looking at the following query from the inside out:
REM
REM a) order all the rows in the table, TOP, with c1 ascending and c2
REM descending via an in-line view. Note the use of order bys in REM in-line views is an Oracle8i feature. REM b) from this returned data take the top 3 values of c2, via rownum REM (since the data is already ordered), for the current value of c1.REM c) cast the 3 returned values of c2 to a nested table of numbers. The
REM reason a nested table is used is because if we were to simply use REM another in-line view for the select where rownum then we would REM not be able to tie this to the current row in the select from TOP REM itself. Thus we would only be able to return the top 3 rows in for REM the first value of c1. By casting the returned data to a nested REM table and then using the TABLE function to unnest it again we can REM perform a correlated subquery and so achieve what we require.REM d) use the Oracle8i TABLE function to treat the nested table as though
REM it is a real table along side TOP. So TOP gives us the values of REM c1 and the TABLE function returns the top 3 values of c2 that REM correspond to that value of c1.REM e) the distinct and order by on the outer query then return the data in
table ( cast ( multiset ( select c2 from ( select c1, c2 from top order by c1, c2 desc ) t where t.c1 = a.c1 and rownum <= 3 ) as num_tab ) )
REM 1 5 REM 1 4 REM 1 3 REM 2 5 REM 2 4 REM 2 3 REM 3 5
table ( cast ( multiset ( select c2 from ( select /*+ INDEX(top,itop) */ c1, c2 from top ) t where t.c1 = a.c1 and rownum <= 3 ) as num_tab ) )
table ( cast ( multiset ( select c2 from ( select /*+ INDEX(top,itop) */ c1, c2 from top where c1 in (1,3) ) t where t.c1 = a.c1 and rownum <= 3 ) as num_tab ) )
REM 1 5 REM 1 4 REM 1 3 REM 3 5 REM 3 4 REM 3 3
table ( cast ( multiset ( select empno from ( select deptno, empno from emp order by deptno, empno desc ) t where t.deptno = a.deptno and rownum <= 2 ) as num_tab ) )
REM 10 7934 REM 10 7839 REM 20 7902 REM 20 7876 REM 30 7900 REM 30 7844
> -----Original Message-----
> From: Koivu, Lisa
> Sent: Wednesday, January 10, 2001 3:01 PM
> To: Multiple recipients of list ORACLE-L
> Subject: Top N query
>
> OK, I apologize in advance, I know this has been discussed many times.
>
> I need to generate the top N, in this case 3, values for a query, like the
> example shown below. It has to be done in SQL, because I need to return
> this as a refcursor. (OPEN refcurcor FOR...)
>
> category1 10
> category1 14
> category1 2
> category1 25
> category2 14
> category2 13
> category2 55
> category2 5
> category3 14
> category3 1
> category4 5
>
> I need to display this:
>
> category1 25
> category1 14
> category1 10
> category2 55
> category2 14
> category2 13
> category3 14
> category3 1
> category4 5
>
> Can you hear me cursing....
>
> Thanks in advance for any suggestions.
>
> Lisa Rutland Koivu
> Oracle Database Administrator
> Qode.com
> 4850 North State Road 7
> Suite G104
> Fort Lauderdale, FL 33319
Received on Wed Jan 10 2001 - 14:59:31 CST
![]() |
![]() |