簡體   English   中英

MySQL:了解映射表

[英]MySQL: Understanding mapping tables

在為具有多對多關系的業務目錄構建類別導航系統時,我理解創建映射表是一種好習慣。

類別表(CategoryId,CategoryName)
業務表(BusinessId,BusinessName)
類別映射表(BusinessId,CategoryId)

當我加入Category表和Business表來創建映射表時,這會給我一個包含每個可能的業務和類別關系的表嗎?

我有800個類別和1000個商家信息。 那會不會給我一張包含800,000種可能關系的表格。 如果是這樣,我將如何只關注存在的關系? 我是否必須通過所有列表(800,000)將其標記為真或假?

我對此非常困惑,所以任何幫助都會非常感激。

使用多對多關系時,處理此問題的唯一現實方法是使用映射表。

假設我們有一所學校,老師和學生,一個學生可以有多個老師,反之亦然。

所以我們制作3張桌子

student
  id unsigned integer auto_increment primary key
  name varchar

teacher
  id unsigned integer auto_increment primary key
  name varchar

link_st
  student_id integer not null
  teacher_id integer not null
  primary key (student_id, teacher_id)

學生表將有1000條記錄
教師表將有20條記錄
link_st表將包含與鏈接一樣多的記錄(非20x1000,但僅適用於實際鏈接)。

選擇
您可以選擇每位教師使用的學生:

SELECT s.name, t.name 
FROM student
INNER JOIN link_st l ON (l.student_id = s.id)   <--- first link student to the link-table
INNER JOIN teacher t ON (l.teacher_id = t.id)   <--- then link teacher to the link table.
ORDER BY t.id, s.id

通常,您應該始終在此處使用inner join

建立鏈接
當您將教師分配給學生時(反之亦然,這是相同的) 你只需要這樣做:

INSERT INTO link_st (student_id, teacher_id) 
   SELECT s.id, t.id 
   FROM student s 
   INNER JOIN teacher t ON (t.name = 'Jones')
   WHERE s.name = 'kiddo'

這有點濫用內連接,但只要名稱是唯一的,它就會起作用。
如果你知道id,你可以直接插入它們。
如果名稱不唯一,則將失敗 ,不應使用。

如何避免重復鏈接
避免重復鏈接非常重要,如果你有這些鏈接會發生各種不好的事情。
如果要防止在鏈接表中插入重復鏈接,可以在鏈接上聲明unique索引(推薦)

ALTER TABLE link_st
  ADD UNIQUE INDEX s_t (student_id, teacher_id); 

或者您可以在insert語句中進行檢查(不是真的推薦,但它可以工作)。

INSERT INTO link_st (student_id, teacher_id) 
  SELECT s.id, t.id
  FROM student s
  INNER JOIN teacher t ON (t.id = 548)
  LEFT JOIN link_st l ON (l.student_id = s.id AND l.teacher_id = t.id)
  WHERE (s.id = 785) AND (l.id IS NULL)

如果該數據不在link_st表中,則僅選擇link_st如果該數據已在link_st中, link_st返回任何內容。 因此它將拒絕插入重復值。

如果你有一個表學校,這取決於學生是否可以在多所學校注冊(不太可能,但我們假設),教師可以在多所學校注冊。 非常可能。

table school
  id unsigned integer auto_increment primary key
  name varchar

table school_members
  id id unsigned integer auto_increment primary key
  school_id integer not null
  member_id integer not null
  is_student boolean not null

您可以列出學校中的所有學生:

SELECT s.name
FROM school i
INNER JOIN school_members m ON (i.id = m.school_id)
INNER JOIN student s ON (s.id = m.member_id AND m.is_student = true)

當我加入Category表和Business表來創建映射表時,這會給我一個包含每個可能的業務和類別關系的表嗎?

是。

我是否必須通過所有列表(800,000)將其標記為真或假?

不,您需要使用ON -clause來設置join-conditions。

SELECT <columns> FROM categories as c 
INNER JOIN mapping AS m
    ON m.CategoryId = c.CategoryId
INNER JOIN businesses as b
    ON m.BusinessId = b.BusinessId

在嘗試建模多對多關系或一對多關系時,應使用映射表。

例如,在地址簿應用程序中,特定聯系人可以屬於零個,一個或多個類別。 如果您將業務邏輯設置為聯系人只能屬於一個類別,則可以將聯系人定義為:

Contact
--------------
contactid (PK)
name
categoryid (FK)

Category
--------------
categoryid (PK)
categoryname

但是,如果您希望允許聯系人擁有多個電子郵件地址,請使用映射表:

Contact
--------------
contactid (PK)
name

Category
--------------
categoryid (PK)
categoryname

Contact_Category
--------------
contactid (FK)
categoryid (FK)

然后,您可以使用SQL來檢索聯系人分配到的類別列表:

從類別a,聯系人b,Contact_Category c中選擇a.categoryname,其中a.categoryid = c.categoryid,b.contactid = c.contactid和b.contactid = 12345;

select a.categoryname 
from Category a
inner join Contact_Category c on a.categoryid=c.categoryid
inner join Contact b on b.contactid=c.contactid
where b.contactid=12345;

你只把真正的關系放在映射表中。 所以平均而言,一個企業屬於兩個類別,那么在你的例子中,映射表中只有2000條記錄,而不是800,000條

“當我加入Category表和Business表來創建映射表時”,你不要加入這兩個表來創建映射表。 您創建一個實際的物理表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM