查询A喜欢B,B喜欢C,两度分离

时间:2011-03-10 21:11:36

标签: mysql sql postgresql

假设您有下表名为Likes:

A|B
---
a|b
a|f
a|e
a|i
b|a
b|i
c|d
e|p

在此表中,A中的值表示“喜欢”B中的人的人。因此,a喜欢b,喜欢f,喜欢e等等。 如何撰写查询,以便获得与每个用户分开两度的不同用户的数量?举个例子,如果a喜欢b,那么b是与a的一个分离度。如果a喜欢b,而b喜欢c,那么c是与a的两个分离度。再举一个例子,如果a喜欢b,而b喜欢a,则a与自身分离两度(我们不排除循环)。所以输出应该是这样的:

User|CountOfUsersWhoAreTwoDegreesFromUser
-----------------------------------------
 a  |  -
 b  |  -
 c  |  -
 e  |  -

现在,我不确定每个用户的计数是什么,所以我没有在上表中写出来。此外,桌子上没有人喜欢自己。因此,你不会看到像喜欢中的一个组合,或喜欢中的b | b。任何人都可以帮我解决这个问题吗?

4 个答案:

答案 0 :(得分:2)

select primary.A, count(*)
from likes primary
   inner join likes secondary on primary.B = secondary.A
group by primary.A

答案 1 :(得分:1)

由于您只需要同时考虑两个连接,因此可以使用连接来完成。 (如果你必须考虑Likes关系的完全关闭,那么你将需要递归的全部功能,例如Dijkstra算法的实现。)

SELECT X.A AS user, COUNT(DISTINCT Y.B) AS countOfUsersWhoAreTwoDegreesFromUser
FROM Likes AS X
    INNER JOIN Likes AS Y
    ON X.B = Y.A
GROUP BY user

编辑:要明确的是,对于任何固定分离度,这个问题都是简单而合理的。

编辑2:这是一个变体解决方案,可以防止用户被自己计算两度。这与文字问题描述不同,但可能是预期的。

SELECT X.A AS user, COUNT(DISTINCT Y.B) AS countOfUsersWhoAreTwoDegreesFromUser
FROM Likes AS X
    INNER JOIN Likes AS Y
    ON X.B = Y.A
WHERE X.A <> Y.B
GROUP BY user

答案 2 :(得分:0)

注意:此方法不可扩展... 如果你只对两度感兴趣,我们可以去自我加入...

条件T1.A&lt;&gt; T2.B是过滤出A喜欢的A,应用了Distinct使得即使A像C一样由两个不同的路径两度,它仍然算作1。

SELECT T.A, Count(T.B)
FROM
(
  SELECT  DISTINCT T1.A, T2.B 
    FROM Table1 T1
   INNER JOIN Table1 T2 on T1.B = T2.A AND T1.A <> T2.B
) T
GROUP BY T.A

答案 3 :(得分:0)

为了处理学位的任意值,可以在PostgreSQL中使用CTE:

with recursive graph (a, b, path, degree) as
(
  select a, b, array[a::text, b::text] as path, 1 as degree
  from likes

  union all

  select l.a, l.b, g.path || l.b::text, g.degree + 1
  from likes l
    join graph g on l.a = g.b and l.b  g.a
)
select *
from graph
where degree = 2