Вы можете использовать оконные функции:
select t.*
from (select t.*,
rank() over (partition by user order by min_date) as seqnum
from (select t.*,
min(date) over (partition by user, product) as min_date
from t
) t
) t
where seqnum = 1;
Или только с одним подзапросом:
select t.*
from (select t.*,
min(date) over (partition by user, product) as min_date_up,
min(date) over (partition by user) as min_date_u
from t
) t
where min_date_u = min_date_up;
Вы можете интерпретировать это как «вернуть все строки, где у продукта минимальная дата для пользователя ".
Здесь - это дб <> скрипка.