Selecting top n elements of a group in Oracle

前端 未结 5 681
执念已碎
执念已碎 2020-12-10 22:14

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

相关标签:
5条回答
  • 2020-12-10 22:48
    select name, VALUE, TIMESTAMP 
    from (select name, VALUE, TIMESTAMP, rank() over (partition by NAME order by TIMESTAMP DESC) rank 
         from logs) 
    where rank <= 3
    
    0 讨论(0)
  • 2020-12-10 22:51

    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;
    
    0 讨论(0)
  • 2020-12-10 22:57

    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> 
    
    0 讨论(0)
  • 2020-12-10 23:05
    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".

    0 讨论(0)
  • 2020-12-10 23:14

    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
    
    0 讨论(0)
提交回复
热议问题