Этот тип запроса обычно решается с помощью оконных функций
select *
from (
SELECT b.product_id,
b.category_id,
a.revenue,
dense_rank() over (partition by b.category_id, b.product_id order by a.revenue desc) as rnk
from A
join b ON B.product_id = A.product_id
where a.order_date between date '2006-01-01' AND date '2006-01-31'
) as t
where rnk <= 3
order by product_id, category_id, revenue desc;
dense_rank()
также будет иметь дело со связями (продукты с одинаковым доходом в той же категории), так что вы можете получить более 3 строк для продукта / категории.
Если один и тот же продукт может появляться более одного раза в таблице b
(для одной и той же категории), вам необходимо объединить его с GROUP BY, чтобы получить сумму всех доходов:
select *
from (
SELECT b.product_id,
b.category_id,
sum(a.revenue) as total_revenue,
dense_rank() over (partition by b.category_id, a.product_id order by sum(a.revenue) desc) as rnk
from a
join b on B.product_id = A.product_id
where a.order_date between date '2006-01-01' AND date '2006-01-31'
group by b.product_id, b.category_id
) as t
where rnk <= 3
order by product_id, category_id, total_revenue desc;
При объединении оконных функций и GROUP BY оконная функция будет применяться после GROUP BY.