Я бы написал так:
select user, product, count(*) as c,
count(*) * 1.0 / sum(count(*)) over (partition by user) as ratio
from table
group by user, product;
Простой алгоритм, который используется на практике (например, в Прологе), является экспоненциальным для патологических случаев.
Существует теоретически более эффективный алгоритм Мартелли и Монтанари (IIRC он линейный), но он намного медленнее для простых случаев, которые встречаются на практике, поэтому он редко используется.