Базовыми данными по общим покупкам являются самостоятельные объединения и group by
:
select p1.product, p2.product, count(*) as in_common
from purchases p1 join
purchases p2
on p1.buyer = p2.buyer
group by p1.product, p2.product;
Чтобы получить счет для одного (или другого), тогда join
:
select p1.product, p2.product, pp.cnt, count(*) as in_common
from purchases p1 join
purchases p2
on p1.buyer = p2.buyer join
(select p1.product, count(*) as cnt
from purchases
group by p1.product
) pp
on pp.product = p1.product
group by p1.product, p2.product, pp.cnt;
В качестве альтернативы, вы можете использовать оконные функции:
select p1.product, p1.cnt, p2.product, count(*) as in_common
from (select p1.*,
count(*) over (partition by p1.product) as cnt
from purchases p1
) p1 join
purchases p2
on p1.buyer = p2.buyer
group by p1.product, p2.product, p1.cnt;
Здесь - тестер, демонстрирующий его работу.