选择所有从未合作过但但都与第三人合作的人

时间:2018-01-16 17:21:38

标签: sql database postgresql

所以,让我们试着让这个变得简单。 假设我有三张桌子(我将在这里发布感兴趣的有用属性):

DEVELOPERS( dev_id, ...)
COLLABORATIONS( activity_id, dev_id, ... )
ACTIVITY( activity_id, ...)

协作是一个表,用于将完成的所有活动链接到处理它们的开发人员(它的主键是activity_id, dev_id对)。重要的是,在一个单独的Activity上可以至少有1个dev,但是它们的最大值是未定义的(没有限制)

我需要知道的是,并且我很难理解,所有对(并且只有一对)开发人员的dev_id是如何从未合作的(也就是没有合作的元组)相同的activity_id和他们的dev_id)但是,他们两个都与(至少一个)相同的“第三开发者”在其他协作中合作

我需要得到一个行表,其中有两列包含满足要求的每对开发者。

请注意,我并不是要求只检查与两个开发人员合作的协作,而是检查其中的每一个。

我的第一个想法是先找到所有合作的开发人员,从所有开发人员列表中删除他们的dev_id(可能还有一个除外?)(所以我只有那些从未在自己内部合作过的人)并从那里开始。

有任何想法或建议吗?

添加澄清示例:

activity_id     dev_id
1               2
1               3
1               5

2               1
2               3

3               1
3               4
3               2

所以这里例如dev 3和4从未一起工作,但两者都至少与另一个相同的开发人员(在这种情况下为dev 1和dev 2)

Dev 1和5从未一起工作,但两者都与至少另一个相同的dev(在这种情况下为dev 3和dev 2)合作

Dev 4和dev 5从未一起工作,但两者都与至少另一个相同的dev(在这种情况下为dev 2)合作

所以查询应该返回

devA    devB
3       4
1       5
4       5

2 个答案:

答案 0 :(得分:0)

我相信有人能够改进这一点,但我认为它有效(见fiddle):

SELECT DISTINCT
    c.dev_id, 
    d.dev_id
FROM 
    COLLABORATIONS c, 
    DEVELOPERS d
WHERE 
    c.dev_id > d.dev_id AND
    (
    SELECT 
        ca.activity_id 
    FROM 
        COLLABORATIONS ca 
    WHERE 
        ca.dev_id = c.dev_id AND 
        ca.activity_id  IN 
        (
        SELECT 
            cb.activity_id 
        FROM 
            COLLABORATIONS cb 
        WHERE cb.dev_id = d.dev_id
        ) 
    LIMIT 1) IS NULL AND
(
SELECT 
    cc.dev_id 
FROM 
    COLLABORATIONS cc 
WHERE 
    cc.activity_id IN
    (
    SELECT 
        cd.activity_id 
    FROM 
        COLLABORATIONS cd 
    WHERE 
        cd.dev_id = c.dev_id) AND 
        cc.dev_id IN 
        (
        SELECT 
            ce.dev_id 
        FROM 
            COLLABORATIONS ce 
        WHERE 
            ce.activity_id IN
            (
            SELECT 
                cf.activity_id 
            FROM 
                COLLABORATIONS cf 
            WHERE 
                cf.dev_id = d.dev_id)
            )  
    LIMIT 1) IS NOT NULL

答案 1 :(得分:0)

这是非常简单的方法

SELECT DISTINCT a.dev_id, d.dev_id
FROM COLLABORATIONS AS a
JOIN COLLABORATIONS AS b ON a.activity_id = b.activity_id AND a.dev_id<>b.dev_id
JOIN COLLABORATIONS AS c ON b.dev_id = c.dev_id
JOIN COLLABORATIONS AS d ON c.activity_id = d.activity_id AND c.dev_id<>d.dev_id
WHERE a.dev_id<d.dev_id

EXCEPT

SELECT DISTINCT a.dev_id, b.dev_id
FROM COLLABORATIONS AS a
JOIN COLLABORATIONS AS b ON a.activity_id = b.activity_id AND a.dev_id<b.dev_id

ORDER BY 1, 2

通过第三人连接的所有对都需要减去所有直接对。由于mysql不支持EXCEPT,你必须更换它,我会把它留作练习。