2011-03-10 65 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