假设您有下表名为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。任何人都可以帮我解决这个问题吗?
答案 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