Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

postgres: get top n occurrences of a value within each group

I have a simple table like this:

user    letter
--------------
1       A
1       A
1       B
1       B
1       B
1       C

2       A
2       B
2       B
2       C
2       C
2       C

I want to get the top 2 occurrences of 'letter' per user, like so

user    letter  rank(within user group)
--------------------
1       B       1
1       A       2

2       C       1
2       B       2

or even better: collapsed into columns

user    1st-most-occurrence  2nd-most-occurrence
1       B                   A
2       C                   B

How can I accomplish this in postgres?

like image 849
Hoff Avatar asked Nov 19 '25 16:11

Hoff


2 Answers

Something like this:

select *
from (
    select userid, 
           letter, 
           dense_rank() over (partition by userid order by count(*) desc) as rnk
    from letters
    group by userid, letter
) t
where rnk <= 2
order by userid, rnk;

Note that I replaced user with userid because using reserved words for columns is a bad habit.

Here is an SQLFiddle: http://sqlfiddle.com/#!12/ec3ec/1

with cte as (
    select 
        t.user_id, t.letter,
        row_number() over(partition by t.user_id order by count(*) desc) as row_num
    from Table1 as t
    group by t.user_id, t.letter
)
select
    c.user_id,
    max(case when c.row_num = 1 then c.letter end) as "1st-most-occurance",
    max(case when c.row_num = 2 then c.letter end) as "2st-most-occurance"
from cte as c
where c.row_num <= 2
group by c.user_id

=> sql fiddle demo

like image 39
Roman Pekar Avatar answered Nov 22 '25 05:11

Roman Pekar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!