2016-10-03 64 views
0

假设我有如下表:甲骨文:如何找到重叠行

User_ID Activity_ID 
123  222 
123  333 
124  222 
124  224 
124  333 
125  224 
125  333 

我想重叠的不同组合,如下面的返回计数的用户:

Activity_ID_1 Activity_ID_2 Count_of_Users 
222   333   2 
222   224   2 

在上面的例子中,有2个用户完成了223和333.

我不想手动定义每个组合,因为我正在使用93个不同的activity_ids。有没有一种方法可以纯粹在Oracle SQL中执行此操作?

+0

我只看到用户'124'为已经覆盖'的范围内2 22'到'224'。 –

+0

如果某些用户完成了3项活动(相同的3项活动),您希望看到输出结果如何? –

+0

我对活动ID本身不感兴趣。例如,用户123和124都完成了222和333的活动,那么这个组合的用户数应该是2. – datatista

回答

1

假设你有一个activity表活动ID的,而你想只计算不同用户谁了相同的两个活动(有两次两项活动相同的用户将不计):

select a1.activity_id, a2.activity_id, count(distinct f.user_id) 
from activity a1 inner join facts f on a1.activity_id = f.activity_id 
        inner join activity a2 on a2.activity_id = f.activity_id 
where a1.activity_id < a2.activity_id 
group by a1.activity_id, a2.activity_id 
having count(distinct f.user_id) >= 2 
; 

facts是你事实表的名字(你在问题中显示的那个)。

编辑:如果facts表(或视图或子查询或其他)已被user_id“截然不同”,则从我的解决方案中删除“distinct”;这将使它更有效率。注意:“distinct”会出现两次,一次出现在SELECT中,另一次出现在HAVING中。

+0

谢谢,这个工程很好。我唯一需要补充的是,有时候我得到了一列填充的activity_id1,但是activity_id2为空,我通过设置'where activity_id2 not null'来解决这个问题。 – datatista

+0

@datatista - 哦...你说的对,一般来说NULL是不等于其他任何东西,但GROUP BY中的空值被组合在一起。好的捕捉和解决方案!然而......第二个想法......来自内部联接,并且activity_id是表活动中的PK,如何在首先查询结果中获得NULL?我错过了一些东西...... – mathguy

0

甲骨文设置

CREATE TABLE data (User_ID, Activity_ID) AS 
SELECT 123, 222 FROM DUAL UNION ALL 
SELECT 123, 333 FROM DUAL UNION ALL 
SELECT 124, 222 FROM DUAL UNION ALL 
SELECT 124, 224 FROM DUAL UNION ALL 
SELECT 124, 333 FROM DUAL UNION ALL 
SELECT 125, 224 FROM DUAL UNION ALL 
SELECT 125, 333 FROM DUAL; 

CREATE TYPE INTLIST AS TABLE OF INT; 
/

查询

WITH Activities (User_IDs, Activity_ID) AS (
    SELECT CAST(COLLECT(User_ID) AS INTLIST), 
     Activity_ID 
    FROM data 
    GROUP BY Activity_ID 
) 
SELECT a.Activity_ID, 
     b.Activity_ID, 
     CARDINALITY(a.User_IDs MULTISET INTERSECT b.User_IDs) AS "Count" 
FROM Activities a 
     INNER JOIN 
     Activities b 
     ON (CARDINALITY(a.User_IDs MULTISET INTERSECT b.User_IDs) > 1 
      AND a.Activity_ID < b.Activity_ID); 

输出

ACTIVITY_ID ACTIVITY_ID  Count 
----------- ----------- ---------- 
     222   333   2 
     224   333   2