創建和查詢數據庫以設置組、使用者、項目和點之間的層次關聯
我正在使用三種實體類型,組、使用者和項目。組由使用者組成,使用者由項目組成。
現在,我必須使用第四種實體類型:Point。我希望能夠在組、使用者和項目級別上分配這些積分。點是可以在多個級別上分配的實體。
假設我在“第 1 組”中有一個點,那麼所有使用者和項目都可以訪問它。因此,假設我添加了一個新使用者並將其附加到“組 1”,那麼它將自動訪問應用程序中的該點,因為它是“組 1”的成員。
假設我想給“A組”一個點,那麼一個點應該與該組、所有使用者和這些使用者的項目相關聯。
例如,如果我給“使用者 2”一個點,則該點與該使用者以及與該使用者關聯的所有項目相關聯。
我對這三個級別的想法是動態添加新數據並因此繼承這些權限,同時如果您決定只有一個項目應該能夠看到它,則能夠將 Point 權限一直添加到 Item 級別。
我將如何為這種情況制定數據方案?
到目前為止我的嘗試
實體關係圖
我嘗試繪製重要實體類型如何在我的腦海中連接的圖表:
數據操作
將 GROUP 1 分配給 POINT 1 的範例:
INSERT INTO Point_group (group_id,point_id) VALUES (1,1);
將 USER 1 和 2 分配給 POINT 1 的範例:
INSERT INTO Point_user (user_id,point_id) VALUES (1,1); INSERT INTO Point_user (user_id,point_id) VALUES (2,1);
然後編寫一些邏輯來確定基於此標記的條目。我覺得有點失落。
我認為您的方法 - 擁有 3 個連接表(
Point_group
,Point_user
,Point_item
)是合理的。這種設計的考慮是:
- 添加“權限”很容易 - 如果使用者選擇添加到
User
,那麼您插入Point_user
- 以 開頭
Point
,如果您想詢問“哪些組、使用者和項目有權限?” 那麼您將需要針對所有 3 個連接表建構一個查詢。您可以在您的應用程序中有 3 個單獨的查詢和聚合結果,或者您可以有一個UNION
3SELECT
秒的單個查詢(一列表示SELECT
包含一行的 ,其值如user
等)- 如果您想從組、使用者或項目開始,並詢問“該組/使用者/項目允許哪些點?” 那麼你的查詢越往下越複雜。例如 - 如果您從一個項目開始,您必須查詢
Point_item
具有該項目 ID 的所有行。您還必須找到所有連結User
的行 - 對於這些行中的每一行,檢查Point_user
. 同樣,您必須找到所有連結的Group
行,然後搜尋Point_group
所有匹配項。在直接的 SQL 中,這將是一個很大的SELECT
- 但這可能完全沒問題 - 這只是需要考慮的事情。以另一種方式來解決這個問題 - 你有什麼選擇?
- 您可以有一個表以某種方式將權限從點映射到其他對象。它的設計當然會有
point_id
,然後是一個列來指定這個點映射到什麼 - 即。Group
,User
, 或Item
. 然後,當然,您需要一個id
列 - 它將連結到相關表。我之前已經看到過類似這種替代方案的模型,坦率地說,我認為這是一個更糟糕的設計。這樣的設計意味著當你想從你的點連接到另一個實體時,你需要檢查這個映射標誌列,以便決定應該連接哪個表。它是混亂、醜陋和性能密集型的。
然而,還有另一種選擇:
- 將您的 Group、User 和 Item 表合併到一個表中。
Entity
在這個例子中,如果想要一個更好的名字,就叫它。您現在需要一個標誌來指示給定行上的實體類型 - 例如Group
,User
和Item
。您還需要指定一列parent
- 這樣Item
您就可以為一行指定User
其父級。最後一個建議意味著您只需要一個實體和點之間的映射表。但是,再次執行上述所有場景 - 如果您從一個點開始,並且想知道哪些組、使用者和項目有權查看,您將如何查詢?獲取所有實體的列表將是一個簡單的查詢,但如果要列出所有實體的所有成員,則需要實體表多次連接自身。
最後一種設計可能有其好處,但我認為您的原始提案是最容易維護和理解的。