2015-08-28 64 views
0

我想要設計一個非常簡單的表,用於存儲社區中朋友的數據。避免朋友表中的數據冗餘

因此,我分別存儲了2位朋友的userId

目標

用戶想要加載他/她的朋友列表。

t_friends選項1:

enter image description here

查詢

SELECT * FROM t_friend WHRE user_id = 10 

10是正在尋找他的朋友列表中的用戶的當前userId和他有1個朋友userId(20)

這種方式userId (10)找到他的朋友(20)但是如果userId(20)找他的朋友呢? 該查詢結合userId

這使我到包含冗餘數據的另一種設計:

t_friends選項2:現在

enter image description here

userId (10)負載:

SELECT * FROM t_friend WHRE user_id=10 

類同,查詢因此userId(20)將是:

SELECT * FROM t_friend WHRE user_id=20 

但是冗餘怎麼樣?這導致我然後使用表設計選項1的查詢:

SELECT * FROM t_friend WHERE user_id=10 OR friend_id=10 

我有一種感覺,有一個更聰明的方法來解決這個問題。你對這種結構有任何經驗嗎?

感謝

+2

什麼冗餘?你所做的完全沒問題,不管有什麼人會寫關於它的東西,都沒有更聰明的辦法。您查詢用戶的朋友。你的數據是正常化的,一切都很完美。如果你可以通過嘗試「優化」來實現任何目標,那麼它就會破壞整個事情,產生不必要的複雜查詢並使系統難以維護。無論用戶使用SQL有什麼經驗或者有什麼經驗,當人們看到你創建的桌面時,乍看起來一切都很合理。 TL; DR:不要改變任何東西。 – Mjh

+0

謝謝@Mjh。但是通過這種方式,我們可以獲得更多的數據。而不是有例如10GB你將有20GB的掃描等。 –

+2

@bub您使用的最終查詢完全正確,在我看來,問題正在被過度思考。每個關係一行,使用OR查詢,完成。你可以在那裏拋出一個IF來避免它在php中:'SELECT IF(user_id = 10,friend_id,user_id)AS target_id FROM t_friend WHERE user_id = 10或friend_id = 10' –

回答

2

我認爲這是存儲關係數據的唯一方法。在存儲關係時,嘗試將最小值作爲userId和max值存儲爲friendId。使這兩個值完全獨一無二,並且不會得到任何重複值。當您搜索用戶使用類似下面

SELECT * FROM t_friend WHERE user_id=10 OR friend_id=10 
+0

謝謝。爲什麼最小和最大分離? –

+0

表格在插入值時不想執行其他搜索 –

-1

您可能需要使用下面的查詢驗證了,如果你的用戶是不是已經另一個第一的朋友:

INSERT INTO t_friend (userId, friendId) 
SELECT 10, 20 
WHERE NOT EXISTS ( SELECT userId 
        FROM t_friend 
        WHERE userId = 20 
        AND friendId = 10) 

由於約冗餘校驗here這(法國)的話題。

+0

謝謝。但是這並沒有幫助,因爲你不知道朋友ID。但是,您的查詢假設知道一個用戶ID爲20. –

+0

因此,您應該添加另一個關於如何插入值的精度,我猜你在插入該行之前知道兩個用戶的ID,對吧? –

+0

是的,當我插入時,我知道兩個ID。但是,您的意思是另一個精度? –

2

添加字段friendship_key:

ALTER TABLE t_friend ADD friendship_key十進制(22,11);

CREATE UNIQUE INDEX friendship_key_unique ON t_friend(friendship_key);

和PHP部分:

$friends = [$userId, $friendId]; 
$key = min($friends).'.'.max($friends); 

$q = "SELECT * FROM t_friend WHERE friendship_key = ".$key; 

插入:

$friends = [$userId, $friendId]; 
$key = min($friends).'.'.max($friends); 

$q = "INSERT INTO t_friend (friendship_key, userId, friendId) VALUES (".implode(',', [$key, $userId, $friendId]).")"; 

使用VARCHAR友誼密鑰而不是我用十進制,以儘量減少相關的關鍵數據。

爲了簡單起見只創建功能:

function insertFriendship($user1, $user2) { 
    $key = min([$user1, $user2]).'.'.max([$user1, $user2]); 
    $q = "INSERT INTO t_friend (friendship_key, userId, friendId) VALUES (".implode(',', [$key, $user1, $user2]).")"; 
    mysql_query($q); 
} 

function getFriendsOf($user) { 
    $q = "SELECT * FROM t_friends WHERE ".$user." IN (userId, friendId)"; 
    return mysql_query($q); 
} 

function areFriends($user1, $user2) { 
    $key = min([$user1, $user2]).'.'.max([$user1, $user2]); 
    $q = "SELECT 1 FROM t_friends WHERE friendship_key = ".$key." LIMIT 1"; 
    $q = mysql_query($q); 
    return (mysql_num_rows($q)>0); 
} 
+1

感謝您的努力:)我必須實施您的解決方案,一旦它有效,我會接受。謝謝 –