MySQL: понимание таблиц сопоставления - PullRequest
12 голосов
/ 23 июня 2011

При создании системы навигации по категориям для бизнес-каталога, имеющей отношение многие ко многим, я понимаю, что рекомендуется создать таблицу сопоставления.

Таблица категорий (CategoryId, CategoryName)
Business Table (BusinessId, BusinessName)
Таблица отображения категорий (BusinessId, CategoryId)

Когда я присоединяюсь к таблице категорий и бизнес-таблице для создания таблицы сопоставления, получится ли тогда таблица, содержащая все возможные отношения бизнеса и категории?

У меня 800 категорий и 1000 бизнес-списков. Тогда это даст мне таблицу, содержащую 800 000 возможных отношений. Если так, то как бы я сосредоточился только на тех отношениях, которые существуют? Должен ли я просмотреть все списки (800 000), помечая их как истинные или ложные?

Я действительно запутался в этом, поэтому любая помощь будет высоко ценится.

Ответы [ 4 ]

25 голосов
/ 23 июня 2011

При использовании отношений «многие ко многим» единственный реалистичный способ справиться с этим - использовать таблицу сопоставления.

Допустим, у нас есть школа с учителями и учениками, у ученика может быть несколько учителей и наоборот.

Итак, мы делаем 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'

Это неправильное использование внутреннего соединения, но оно работает, пока имена уникальны.
Если вы знаете идентификаторы, вы, конечно, можете просто вставить их напрямую.
Если имена не уникальны, это будет fail и не должно использоваться.

Как избежать повторяющихся ссылок
Очень важно избегать повторяющихся ссылок, если они у вас будут, произойдут всякие плохие вещи.
Если вы хотите запретить вставку дублирующих ссылок в таблицу ссылок, вы можете объявить индекс unique для ссылки (рекомендуется)

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

Или вы можете выполнить проверку в операторе вставки (не очень рекомендуется, но это работает).

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)

Это выберет только 548, 785 , если , что данные еще не находятся в таблице 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)
2 голосов
/ 23 июня 2011

Когда я присоединяюсь к таблице категорий и Бизнес стол для создания картографии стол это тогда даст мне стол который содержит все возможные дела и категория отношений?

Да.

Должен ли я просмотреть все списки (800 000), помечая их как истинные или ложные?

Нет, вам нужно использовать ON -клаузу для установки условий соединения.

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
1 голос
/ 23 июня 2011

Таблицы сопоставления следует использовать, когда вы пытаетесь смоделировать отношение «многие ко многим» или «один ко многим».

Например, в приложении адресной книги конкретный контакт может принадлежать нулюодна или несколько категорий.Если вы установите свою бизнес-логику, согласно которой контакт может принадлежать только к одной категории, вы можете определить свой контакт следующим образом:

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,Контактная категория c, где 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;
1 голос
/ 23 июня 2011

вы кладете только реальные отношения в таблицу сопоставления. Таким образом, в среднем бизнес находится в 2 категориях, тогда в вашем примере в таблице сопоставления будет только 2000 записей, а не 800 000

«Когда я соединяю таблицу категорий и бизнес-таблицу для создания таблицы сопоставления», вы не объединяете эти две таблицы для создания таблицы сопоставления. Вы создаете фактическую физическую таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...