I have an Oracle table which has a name,value,time columns.Basically the table is for logging purposes to store what are the changes made to a particular name,what was the p
select name, VALUE, TIMESTAMP
from (select name, VALUE, TIMESTAMP, rank() over (partition by NAME order by TIMESTAMP DESC) rank
from logs)
where rank <= 3
I offer my quick fix. This query groups and counts in descending order (in the inner query). The Outer query simply allows you to define the number of rows to display (:pRows).
Select * from
(Select
group_field,
count(*) Cnt
From
record_source(s)
Where
Conditions
Order by
Count(*) Desc) x
Where
rownum < :pRows+1;
Is this what you are after?
My test set-up:
SQL> alter session set nls_date_format = 'DD-Mon-YYYY HH24:Mi:SS';
Session altered.
SQL> drop table so_test;
Table dropped.
SQL> create table so_test (
2 n varchar2(32)
3 , v varchar2(32)
4 , t date );
Table created.
SQL>
SQL> insert into so_test values ( 'X' , 'Test1', to_date('01-Jan-2011 12:00:00','DD-Mon-YYYY HH24:Mi:SS') );
1 row created.
SQL> insert into so_test values ( 'X' , 'Test2', to_date('01-Jan-2011 13:00:00','DD-Mon-YYYY HH24:Mi:SS') );
1 row created.
SQL> insert into so_test values ( 'X' , 'Test3', to_date('01-Jan-2011 14:00:00','DD-Mon-YYYY HH24:Mi:SS') );
1 row created.
SQL> insert into so_test values ( 'Y' , 'Test5', to_date('02-Jan-2011 12:00:00','DD-Mon-YYYY HH24:Mi:SS') );
1 row created.
SQL> insert into so_test values ( 'Y' , 'Test6', to_date('03-Jan-2011 12:00:00','DD-Mon-YYYY HH24:Mi:SS') );
1 row created.
SQL> insert into so_test values ( 'Y' , 'Test7', to_date('04-Jan-2011 12:00:00','DD-Mon-YYYY HH24:Mi:SS') );
1 row created.
SQL>
Here is the query:
SQL> select n,v,t from (
2 select n, v , t , rank() over ( partition by n order by t desc) r
3 from so_test
4 ) where r <= 2;
N V T
-------------------------------- -------------------------------- --------------------
X Test3 01-Jan-2011 14:00:00
X Test2 01-Jan-2011 13:00:00
Y Test7 04-Jan-2011 12:00:00
Y Test6 03-Jan-2011 12:00:00
SQL>
select * from (select name, value,
time, ROW_NUMBER OVER (PARTITION BY name ORDER BY name) change_no
from table )
where change_no <= 100 AND name ="abc"
ORDER BY TIME
Assuming name remain same, and changes are made to the "value".
Matthew Watson's answer is not always valid, if ordering column is duplicated, query returns more than "r" rows. The solution is to concatenate an unique value to ordering column, it can be used a primary key of the table. Example:
SELECT * FROM (
SELECT
t.*,
RANK() OVER (PARTITION BY object_type ORDER BY (to_char(created,'YYYYMMDDHH24MISS') || object_id) DESC) rank
FROM ALL_OBJECTS t
)
WHERE rank <= 3