2011-03-10 85 views
1

假设你有如下表命名喜欢:查询一个喜欢B,B喜欢C,分离的两个自由度

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

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

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

现在,我不知道我们的计数会是怎样为每个用户,所以我没有在上表中写。此外,表中没有人喜欢自己。所以你不会在Like中看到类似a |的组合,或者在Like中看到b | b。任何人都可以帮我解决这个问题吗?

+0

A不具有唯一值... – fredley 2011-03-10 21:13:53

+0

输入有误,更新它 – Boobie 2011-03-10 21:16:04

+0

注意,因为你已经表述的问题,如果(A,B)和(B,A),然后将被算作距离自身两度。 – 2011-03-10 21:30:10

回答

1

既然您只需要考虑一次只有两个连接,这可以通过连接完成。 (如果你不得不考虑喜欢的关系,采用全封闭,那么你就需要递归的全部功能,如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 
+0

它不会处理案例,A喜欢A的两度...就像A - > B,B-> A .... – 2011-03-10 21:33:21

+0

最初发布的答案将处理原始问题中指定的情况,计算A为两度从本身。如果这不是实际意图,那么第二个查询将以更直观明显的方式处理该案例。 – 2011-03-10 21:37:04

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

注意:这个方法是不是可扩展... 如果你有兴趣,并仅在两个学位,我们可以去自加入...

条件T1.A <> T2 .B是滤除甲喜好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 
0

要使用的任意值应付为度, CTE可以在PostgreSQL中使用:

 
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