[英]Many-to-many on same table
有趣的是,我從未遇到過這個!
我從來沒有想到一個人可以在一張桌子上擁有“多對多”的關系 - 直到我開始研究用戶可以互相“交朋友”的系統(社交網絡)。
標准查找表,至少在我習慣使用它的方式,在這里是不合適的。 讓我們保持簡單:
用戶表具有“id”和“name”列。
User_relationship表具有“uid1”和“uid2”,表示“朋友”或“芽”或“好友”或“其他任何”的用戶。
很明顯這里的問題是什么 - uid1和uid2是來自同一個表的同一列的相同數據類型,這意味着唯一鍵變得有缺陷。
例如:uid1 = 1 uid2 = 2
是相同的:
uid1 = 2 uid2 = 1
因此,如果查詢執行錯誤,則可以返回2條記錄或0條記錄。
本着設計好表的精神,我不想兩次掃描整個表以檢查現有值。
處理這個有什么技巧嗎? 這是一個從未發生過的設計問題,它讓我感到煩惱,因為我知道有一些簡單的技巧可以讓它發揮作用。
在你提問之前,我還沒有嘗試過任何東西,因為我已經看到我最喜歡的關聯方式(查找表)不足以滿足我的需求,我需要一些幫助 - 我在SO或Google上找不到任何東西:(
提前致謝。
如果您描述的關系是對稱的,如“Bob是Joe的朋友”意味着“Joe也是Bob的朋友”,那么您可以在代碼中確保2個用戶ID中的較小者繼續第一列,較大的一列在第二列。 這種約束幾乎可以確保查找表中的記錄是唯一的。 這也意味着當您執行查找時,通常必須搜索兩列。
例如,如果您試圖獲取Bob的所有朋友,則必須在任一列中查詢具有Bob ID的記錄。 這會導致更多代碼,並可能對性能產生影響。
如果關系可以是不對稱的,如“Bob是Joe的朋友”並不一定意味着“Joe也是Bob的朋友”,那么每對用戶需要2個條目:Bob - Joe和Joe - Bob。 這意味着您的查找表將包含兩倍的條目,並且您的站點對跟蹤器非常友好:D當然,即使您的關系是對稱的,您仍然可以選擇應用此系統。
使用此方法,如果您想獲得Bob的所有朋友,您只需在第一列中選擇具有Bob ID的記錄。 這可能意味着更快的查找速度和更少的代碼供您編寫,但同樣,這意味着您在數據庫中占用更多空間。
意味着唯一鍵變得有缺陷。
uid1 = 1 uid2 = 2
是相同的:
uid1 = 2 uid2 = 1
不,不是。
例如,在Facebook上,我有一些客戶發出請求成為我從未接受的“朋友”......因為他們只是熟人。
同樣,我可能會將一些人標記為最好的朋友,他們沒有回應,反之亦然。 或許我忽略了一些而他們不是。
基本上, (uid1, uid2)
元組中的信息比僅僅ID更多。
確保在決定在表上添加例如uid1 < uid2
約束之前,您永遠不需要處理這些情況。
這並不罕見。
通常所做的是存在一個表,就像在大多數關系中一樣,它由兩個列組成,每個列是構成主鍵的兩個表的id。
正如您所說的userId1和userId2。 如有必要,可以將屬性添加到關系中(例如友誼分類)。
當用戶1與用戶2成為朋友時,通常有兩個插入,(1,2)和(2,1)。
與defriending相同的事情,需要有兩個刪除。
您最終可能會將自己視為朋友,這可能對系統的實際運行至關重要。 如果用戶只能查看他朋友的照片,那么如果他不是自己的朋友,某些系統可能不允許他看到他自己的照片。
它非常依賴於如何在數據庫之上編寫應用程序。
我同意其他人所說的,對於一個關系(1:2和2:1)有2個插入並不是一個壞主意。 這實際上有助於擴展現代社交網絡中常見的一些功能。 我能想到的一些實際使用案例是關系或其他屬性的描述。 雖然個人仍然是朋友,但他們保持着彼此不同的環境。 在1:2關系中,Bob正在關注Joe的更新並將他列在最好的朋友列表中(添加bff列),而在2:1中Joe沒有Bob在bff列表中並且不關心他的帖子(在列之后) 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.