2012-12-28 63 views
4

我想在數據庫中存儲友誼。我的想法是,當user1與user2成爲朋友時,我將這種友誼存儲起來,這樣如果我需要的話,我可以獲得所有用戶的朋友。起初,我以爲我只是將他們的ID存儲在一張帶有一個插入的表格中,但後來我在查詢分貝時想到了一些複雜問題。爲用戶友誼設計數據庫

如果我有10的用戶ID和20我應該做兩個插入到數據庫時,他們成爲了朋友

ID USER1 USER2 
1 10 20 
2 20 10 

或者是有沒有辦法查詢數據庫,只得到2個用戶特別是用戶的朋友,如果我只是做了一個插件,像這樣

ID USER1 USER2 
1 10 20 

我所知道的第一種方式,絕對可以給我我所期待的,但我想知道這是很好的做法,如果有更好的選擇。如果可以查詢第二種方式,讓我得到結果,我會像所有的用戶10的朋友一樣尋找。

+2

'user1> user2'可以用作tiebreaker。或'user1 wildplasser

回答

5

布拉德·克里斯蒂的建議是很好的。 不過,由於MySQL是不是在優化OR查詢非常好,使用UNION ALL可能更有效:

(SELECT u.id, u.name 
    FROM friendship f, user u 
    WHERE f.user1 = 1 AND f.user2 = u.id) 
UNION ALL 
(SELECT u.id, u.name 
    FROM friendship f, user u 
    WHERE f.user2 = 1 AND f.user1 = u.id) 

Here's a SQLFiddle of it,基於Brad的例子。我修改了friendship表以添加雙向索引以實現高效訪問,並刪除了meaningless id column。當然,有了這樣一個小例子,你不能真正測試真實世界的性能,但比較兩個版本之間的執行計劃可能是有益的。

+0

你這個男人! +1並接受!感謝您的時間! – gmustudent

+0

快速的問題。我不能只用Union而不是Union All?因爲這裏不應該有任何重複的權利? – gmustudent

+1

你可以,但'UNION'需要MySQL來檢查重複項,如果有的話刪除它們。如果你知道不會有重複,那麼'UNION ALL'通常會更快。 –

5

友誼是一種雙向聯繫(所有意圖和目的)。與另一個鏈接不同(比如單向的消息),友誼應該只有一個條目。但是,你所看到的是正確的;你需要對查詢兩列,將得到一個用戶的朋友,但是這很簡單:在兩個方向上查詢表的

-- The uses of `1` below is where you'd insert the ID of 
-- the person you're looking up friends on 
SELECT  u.id, u.name 
FROM  friendship f 
    LEFT JOIN user u 
    ON  (u.id = f.user1 OR u.id = f.user2) 
    AND  u.id <> 1 
WHERE  (f.user1 = 1 OR f.user2 = 1) 

example here