2010-05-21 24 views
6

想象一下,你生活在非常簡單的例子土地 - 和想象你已經有了一個人在一個表你的MySQL數據庫:得到了一桌子的人,我要鏈接到對方是誰,許多一對多,與鏈接是雙向

create table person (
    person_id int, 
    name text 
) 

select * from person; 

+-------------------------------+ 
| person_id |   name | 
+-------------------------------+ 
|   1 |   Alice | 
|   2 |    Bob | 
|   3 |   Carol | 
+-------------------------------+ 

而這些人需要協作/協同工作,讓你有哪個環節一人記錄到其他的鏈接表:

create table person__person (
    person__person_id int, 
    person_id int, 
    other_person_id int 
) 

這樣的設置意味着之間的聯繫人們是單向的 - 即愛麗絲可以鏈接到鮑勃,而鮑勃連接到愛麗絲,甚至w ORSE,愛麗絲可以鏈接到鮑勃 Bob可以同時鏈接到愛麗絲,在兩個單獨的鏈接記錄。由於這些鏈接代表了工作關係,在現實世界中,它們都是雙向的相互關係。在這個設置中,以下是所有可能的:

select * from person__person; 

+---------------------+-----------+--------------------+ 
| person__person_id | person_id | other_person_id | 
+---------------------+-----------+--------------------+ 
|     1 |   1 |     2 | 
|     2 |   2 |     1 | 
|     3 |   2 |     2 | 
|     4 |   3 |     1 | 
+---------------------+-----------+--------------------+ 

例如,person__person_id = 4的上方,當您查看Carol的(爲person_id = 3)簡檔,應該看到與Alice的關係(爲person_id = 1),並且當您查看Alice的個人資料,即使鏈接以其他方式進行,您也應該看到與Carol的關係。

我知道我可以做工會和不同的查詢和諸如此類的東西呈現在用戶界面相互之間的關係,但有沒有更好的辦法?我有一種感覺,有一個更好的辦法,一個地方這個問題會整齊地融化掉通過適當設置數據庫,但我不能看到它。任何人有更好的主意?

+3

這是我從<50代表用戶見過的格式最好的問題!乾杯! – 2010-05-21 05:46:32

+1

我將標記從'mysql many-to-many'更改爲'data-modeling many-to-many'(+1 nice question!) – lexu 2010-05-21 06:07:49

+1

+1陳述得很好的問題。 nit-pick:person__person是一個可怕的表名;只是聲稱它是用於照明目的;) – msw 2010-05-21 06:25:59

回答

3

我不知道如果有配置表一個更好的辦法。我認爲你擁有它們的方式是正確的,並且將是我實施它的方式。

由於您的關係表可以表示單向關係,所以我會建議對待它們。換句話說,對於每一個關係,我都會添加兩行。如果愛麗絲與鮑勃合作,表應該是如下:

select * from person__person; 
+---------------------+-----------+--------------------+ 
| person__person_id | person_id | other_person_id | 
+---------------------+-----------+--------------------+ 
|     1 |   1 |     2 | 
|     2 |   2 |     1 | 
+---------------------+-----------+--------------------+ 

的原因是因爲在很多的ActiveRecord(滑軌)的類似系統,許多一對多表對象是不夠聰明查詢person_id和other_person_id。通過保持兩行,ActiveRecord類似的對象將正常工作。

您應該做的是在代碼級別強制執行數據的完整性。每次在兩個用戶之間建立關係時,應插入兩條記錄。當關系被銷燬時,這兩個記錄應該被刪除。用戶不應該被允許與自己建立關係。

+1

這也具有業務邏輯的優點,即決定不是所有的關聯都是雙向的,而且架構不需要改變。 – msw 2010-05-21 06:18:05

+0

完成並完成!非常感謝 - 我將採用這種方法,因爲user239098和msw都聲明瞭所有原因。 – 2010-05-21 07:54:05

2

有沒有更好的主意。關係數據庫不能執行你所要求的,所以你必須編寫一個特殊的查詢來檢索數據和一個觸發器來執行約束。

要得到相關人士的@person我會去:

SELECT CASE person_id WHEN @person 
      THEN other_person_id 
      ELSE person_id 
     END as related_person_id 
FROM person_person 
WHERE ( [email protected] 
     OR [email protected]) 
+0

始終在where子句中放置()或'或'。如果在添加更多限制之前忘記了,就會發生不好的事情! (答案爲+1) – lexu 2010-05-21 06:11:33

2

我無法看到使用簡單的關係概念。你將不得不添加「商業」代碼來執行你的人際關係。

  • 一種方式是使用插入觸發
  • 執行的第二關係記錄則聲明的記錄中的一個「主」(例如,一個,其中爲person_id比其它_person_id小)
  • 然後根據這些知識爲您的應用程序構建視圖並粘貼代碼(選擇,更新,刪除)。
2

你會發現這篇文章有用:

http://discuss.joelonsoftware.com/default.asp?design.4.361252.31

由於@user貼出你一般都是最好創建兩個記錄每雙向關係(愛麗絲和鮑勃鮑勃愛麗絲在你的例子)。它使得查詢更容易,並且準確地反映了這些關係。如果你確實有真正的單向關係,那麼這是唯一的飛行方式。

+0

謝謝,我讀了這個帖子;它基本上證實了'只存兩次'的解決方案,接着是一大堆吶喊。我很高興stackoverflow是不是這樣:) – 2010-05-21 07:47:00