Search code examples
postgresqllimit

Grouped LIMIT 10 in Postgresql


I have a query:

select
    a.kli,
    b.term_desc,
    count(distinct(a.adic)) as count,
    a.partner_id

from
    ad_delivery.sgmt_kli_adic a
    join wand.wandterms b on a.kli = b.term_code
    join wand.wandterms c on b.term_desc=c.term_desc
    join dwh.sgmt_clients e on a.partner_id::varchar = e.partner_id
    join dwh.schema_names f on e.partner_id::integer = f.partner_id::integer
where
    a.partner_id::integer in (f.partner_id)
    and c.class_code = 969
group by a.partner_id, b.term_desc, a.kli
order by partner_id, count desc;

which brings back counts for certain terms per partner_id. I want to be able to show the top 10 for each of the ~40 partner_id in order by the count desc

the query results look like

db=# SELECT * FROM xxx;
 pid | term_desc | count
----+------------+------
  4 | termdesc1  | 3434
  4 | termdesc2  | 235
  4 | termdesc3  | 367
  4 | termdesc4  | 4533
  5 | termdesc1  | 235
  5 | termdesc2  | 567
  5 | termdesc3  | 344
  5 | termdesc4  | 56
(10k+ rows)

Solution

  • You could add a rank column and then filter the result by the rank :

    select
        a.kli,
        b.term_desc,
        count(distinct(a.adic)) as count,
        a.partner_id,
        RANK() OVER (PARTITION BY a.partner_id order by a.partner_id DESC) AS r
    from
        ad_delivery.sgmt_kli_adic a
        join wand.wandterms b on a.kli = b.term_code
        join wand.wandterms c on b.term_desc=c.term_desc
        join dwh.sgmt_clients e on a.partner_id::varchar = e.partner_id
        join dwh.schema_names f on e.partner_id::integer = f.partner_id::integer
    where
        a.partner_id::integer in (f.partner_id)
        and c.class_code = 969
    group by a.partner_id, b.term_desc, a.kli
    HAVING r < 11
    order by partner_id, count desc;
    

    I have not tested the code, however the trick is ranking the each row of the GROUP BY and filter the resultset with the HAVING clause, keeping only item with a lower rank than 11 (you will get 10 item per group).