SQL查询计算两个表之间的关系

时间:2015-10-16 02:09:34

标签: sql

我有两个带有用户ID的表,另一个表通过存储两个用户ID来表示两个用户之间的关系。如何计算两个用户之间的相互关系,相互关系定义为两个用户都有关系的用户数。

例如,如果我有:

3 - 4
1 - 4
3 - 6
5 - 6
2 - 6
1 - 6

我希望我的查询返回(按顺序)

User1    User2  MutualCount
  1    |    3   |    2
  2    |    3   |    1
  1    |    2   |    1
  1    |    5   |    1
  2    |    5   |    1
  4    |    6   |    1
  3    |    5   |    1

等等......

我正在考虑User1 / User2的某种内部连接,但我无法弄清楚ON部分如何工作,也无法知道如何存储和返回计数。

我很感激任何帮助!

我用它来提取任何两个用户的所有相互关系,但我还没有找到一种方法为所有用户做到这一点

SELECT b.userid,
FROM user b, user c, relation f
WHERE c.user_id = <user id here>
AND (c.user_id = f.user1_id OR c.user_id = f.user2_id)
AND (b.user_id = f.user1_id OR b.user_id = f.user2_id)
INTERSECT
SELECT b.user_id
FROM user b, user c, relation f
WHERE c.user_id = <user id here>
AND (c.user_id = f.user1_id OR c.user_id = f.user2_id)
AND (b.user_id = f.user1_id OR b.user_id = f.user2_id);

3 个答案:

答案 0 :(得分:0)

编辑: 我把它当作第一次尝试出门,尽管它应该立刻显而易见,它无法正常工作。 (例如,第1列和第2列中的任何值都不是完全不相交的,甚至永远不会匹配。)

也许这个?:

select
    case when mr1.user1 < mr2.user2 then mr1.user1 else mr2.user2 end as User1,
    case when mr1.user1 < mr2.user2 then mr2.user2 else mr1.user1 end as User2,
    count(*) as MutualCount
from
    mr mr1 inner join mr mr2 on mr1.user2 = mr2.user1
group by
    mr1.user1, mr2.user2
order by
    case when mr1.user1 < mr2.user2 then mr1.user1 else mr2.user2 end,
    case when mr1.user1 < mr2.user2 then mr2.user2 else mr1.user1 end

@Joel这个问题比起初看起来有点棘手。普通用户可以在两列中的任何一列中,我们都没有处理过。这就是case表达式所在的位置。我相信正确的解决方案如下:

select
    mr1.user1,
    case when mr1.user2 <> mr2.user1 then mr2.user1 else mr2.user2 end as user2,
    count(*) as MutualCount
from
    mr mr1 inner join mr mr2
        on      mr1.user2 in (mr2.user1, mr2.user2) /* match either user... */
            and mr1.user1 <> mr2.user1 /* ...but not when it's the same row */
where
    mr1.user1 < case when mr1.user2 <> mr2.user1 then mr2.user1 else mr2.user2 end
group by
    mr1.user1,
    case when mr1.user2 <> mr2.user1 then mr2.user1 else mr2.user2 end
order by
    mr1.user1,
    case when mr1.user2 <> mr2.user1 then mr2.user1 else mr2.user2 end

http://sqlfiddle.com/#!3/7e652/15

您也可以使用此相同的联接来查找常用用户。只需删除group bycount()

答案 1 :(得分:0)

SELECT user1Id, user2ID, COUNT(*) MutualCount
FROM UserVsUser
GROUP BY user1Id, user2ID
ORDER BY MutualCount DESC

UserVsUser是表示两个用户之间关系的表。

答案 2 :(得分:0)

这将帮助你完成大部分工作:

SELECT r1.user1_id As User1, r2.user1_id As User2, count(*) As MutualCount
FROM relation r1 
INNER JOIN relation r2 ON r1.user2_id = r2.user2_id AND r1.user1_id < r2.user1_id
GROUP BY r1.user1_Id, r2.user1_id
ORDER BY count(*) DESC;

这应该产生与当前接受的答案类似的结果,但代码更少,执行速度更快。

  

SQLFiddle

我从示例数据中了解为什么对(1,3)的计数为2,以及对(2,3)(1,2)和{{1}对的原因所有产生(1,5)。但是,我从示例中无法理解为什么1(1,4)(1,6)会在结果中显示,尤其是在(3,4)(2,6)和示例结果中的(3,6) 。如果你能解释一下,我有一些想法可以填补缺失的部分。