【问题标题】:Select all the pairs of people which never worked together but which both worked with a third person选择所有从未一起工作但都与第三人一起工作的人
【发布时间】:2018-01-17 21:19:44
【问题描述】:

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

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

Collaborations 是一个表格,用于将完成的所有活动链接到从事这些活动的开发人员(它的主键是 activity_id, dev_id 对)。重要的部分是,在一个 Activity 上至少可以工作 1 个开发人员,但最多可以工作(没有限制)

我需要知道并且我发现很难掌握的方法是 dev_ids 的所有开发人员对(并且只有对)从未合作过(也就是没有具有相同 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(在本例中为 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

【问题讨论】:

  • 更新您的问题添加适当的数据样本和预期结果
  • 你的尝试在哪里?您在寻找免费为您工作的人吗?
  • @KoshVery 这就是为什么我要求“想法或建议”,而不是现成的解决方案。我真的被卡住了,因为我不知道如何继续能够在 sql 中进行这种比较(我不习惯使用 db,我是一个前端人员)。我会很高兴回答“这些类型的比较是由 blabla 和 blabla 完成的,明白了吗?”然后我会尝试不发布乱码
  • 这读起来很像数据库课程介绍中的作业问题
  • 请准确标注。这实际上是用于哪个数据库? Postgres <> MySQL 它们具有不同的功能和语法。只选择一个。

标签: sql database postgresql


【解决方案1】:

这是非常简单的方法

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,因此您必须替换它,我将其留作练习。

【讨论】:

  • 您可以在MYSQL 中使用MINUS 代替EXCEPT。您的查询是否也支持 3 个以上的活动?如果是,那么它会正常工作。
  • @Susang 如果最近没有改变,mysql也不支持MINUS。
【解决方案2】:

我确信有人能够对此进行改进,但我认为它有效(请参阅 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

【讨论】:

  • 如果您将 COLLABORATIONS c 替换为 DEVELOPERS c 以消除重复,则它可以工作。但性能似乎不是最理想的,我在 mssql 上对其进行了测试,我的示例连接解决方​​案是 15 分钟和 23 秒。
猜你喜欢
  • 1970-01-01
  • 2010-10-16
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
相关资源
最近更新 更多