Если вы используете Oracle Database, вы можете сравнить вложенные таблицы (коллекции) с операторами мультимножества.И получите количество элементов в коллекции с количеством элементов.
Итак, что вы можете сделать:
- Группировать по itemid, собирая всех пользователей во вложенную таблицу
- Кросс-соединение этого выхода с самим собой
- Используйте мультисетевые операторы пересечения / исключения, чтобы получить необходимое количество элементов в наборах
Что выглядит примерно так:
create table t (
ItemId int, UserId varchar2(10)
);
insert into t values ( 200 , 'user1');
insert into t values ( 200 , 'user3');
insert into t values ( 200 , 'user4');
insert into t values ( 300 , 'user5');
insert into t values ( 300 , 'user3');
commit;
create or replace type users_t as table of varchar2(10);
/
with grps as (
select itemid, cast ( collect ( userid ) as users_t ) users
from t
group by itemid
)
select g1.itemid i, g2.itemid j,
cardinality ( g1.users ) num_i,
cardinality ( g2.users ) num_j,
cardinality ( g1.users multiset intersect g2.users ) i_and_j,
cardinality ( g1.users multiset except g2.users ) i_not_j,
cardinality ( g2.users multiset except g1.users ) j_not_i
from grps g1
cross join grps g2;
I J NUM_I NUM_J I_AND_J I_NOT_J J_NOT_I
200 200 3 3 3 0 0
200 300 3 2 1 2 1
300 200 2 3 1 1 2
300 300 2 2 2 0 0
При необходимости вы можете повысить производительность, пропустив операторы кроме, когда i = j, например:
case
when g1.itemid = g2.itemid then 0
else cardinality ( g1.users multiset intersect g2.users )
end