Найти N наиболее часто встречающихся категорий с N наиболее часто встречающимися подкатегориями для каждой категории - PullRequest
0 голосов
/ 10 декабря 2018

Я пытаюсь сделать один запрос, который будет получать:

Топ, например, 3 самых популярных бренда из списка автомобилей.Для каждого из трех лучших брендов я хочу получить 5 самых популярных моделей.

Я пробовал использовать как стратегию ранжирования / разбиения, так и стратегию distinct ON, но не могу понять, как мне это сделать.пределы для работы в пределах двух запросов.

Вот некоторые примеры данных: http://sqlfiddle.com/#!15/1e81d5/1

Из запроса ранжирования я бы ожидал такой вывод, учитывая данные примера (порядок не важен):

brand       car_mode    count
'Audi'      'A4'        3
'Audi'      'A1'        3
'Audi'      'Q7'        2
'Audi'      'Q5'        2
'Audi'      'A3'        2
'VW'        'Passat'    3
'VW'        'Beetle'    3
'VW'        'Caravelle' 2
'VW'        'Golf'      2
'VW'        'Fox'       2
'Volvo'     'V70'       3
'Volvo'     'V40'       3
'Volvo'     'S60'       2
'Volvo'     'XC70'      2
'Volvo'     'V50'       2

Ответы [ 3 ]

0 голосов
/ 10 декабря 2018

вы можете попробовать, используя cte и оконную функцию row_number()

with cte as
(
select brand,car_model,count(*) as cnt from cars group by brand,car_model
 ) , cte2 as
 (
     select * ,row_number() over(partition by brand order by cnt desc) rn from cte
 )
select brand,car_model,cnt from cte2 where rn<=5

демонстрационная ссылка

0 голосов
/ 10 декабря 2018

Для этого вы можете использовать оконные функции:

select brand, car_model, cnt_car
from (select c.*, dense_rank() over (order by cnt_brand, brand) as seqnum_b
      from (select brand, car_model, count(*) as cnt_car,
                   row_number() over (partition by brand order by count(*) desc) as seqnum_bc,
                   sum(count(*)) over (partition by brand) as cnt_brand
            from cars c
            group by brand, car_model
           ) c
     ) c
 where seqnum_bc <= 5 and seqnum_b <= 3
 order by cnt_brand desc, brand, cnt desc;

Если вы знаете, что у каждой марки (или, по крайней мере, у каждой марки) есть как минимум пять автомобилей, вы можете упростить запрос до:

select brand, car_model, cnt_car
from (select brand, car_model, count(*) as cnt_car,
              row_number() over (partition by brand order by count(*) desc) as seqnum_bc,
              sum(count(*)) over (partition by brand) as cnt_brand
      from cars c
      group by brand, car_model
     ) c
where seqnum_bc <= 5 
order by cnt_brand desc, brand, cnt desc
limit 15
0 голосов
/ 10 декабря 2018

Оказывается, я мог бы использовать LATERAL присоединиться, как предложено в комментариях.Спасибо.

SELECT brand, car_model, the_count
FROM
  (
    SELECT brand FROM cars GROUP BY brand ORDER BY COUNT(*) DESC LIMIT 3 
  ) o1
INNER JOIN LATERAL
  (
    SELECT car_model, count(*) as the_count
    FROM cars
    WHERE brand = o1.brand
    GROUP BY brand, car_model
    ORDER BY count(*) DESC LIMIT 5
  ) o2 ON true;

http://sqlfiddle.com/#!15/1e81d5/9

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...