2012-04-24 4 views
2

Заранее благодарим за вход.SQL: от многих до многих для многих ... это эффективно?

У меня есть 3 объекта:

  • школа
  • Camp
  • Тренер

С помощью следующих соотношений:

  • Школа может иметь несколько лагерей.
  • Школа может иметь несколько тренеров.
  • В лагере может быть несколько школ.
  • В лагере могут быть несколько тренеров.
  • Тренер может иметь несколько школ.
  • Тренер может иметь несколько лагерей.

Многие из многих, School_Camp, очевидно, связывают школу с лагерем с дополнительным полем для даты, чтобы определить год лагеря. Но в одном лагере могут быть несколько тренеров.

:: School_Camp ::

  • School_id
  • Camp_id
  • Дата

было бы лучше для меня, чтобы создать другой многие ко многим, School_Camp_Coach, что ссылки на столы School_Camp и Coach?

:: School_Camp_Coach ::

  • School_Camp_id
  • Coach_id

Если это более эффективный способ сделать это ... я должен дать School_Camp независимый столбец ID, который может быстро вместо ссылки на три поля в качестве идентификатора?

:: School_Camp ::

  • ID *
  • School_id
  • Camp_id
  • Дата

ИЛИ

ли лучше просто иметь ОДИН много для многих таблиц, School_Camp_Coach, с 3 внешними ключами?

:: School_Camp_Coach ::

  • School_id
  • Camp_id
  • Coach_id
  • Дата

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

Еще раз спасибо.

+2

По крайней мере, использовать заглавные буквы, если вы заранее благодарите? – eandersson

+2

Наиболее эффективный в отношении чего? Размер хранилища данных? Время поиска или обновления? Сложность запроса? Для некоторых показателей эффективности это зависит от того, что вы собираетесь делать с данными. Иногда он платит за денормализацию; в других случаях это не так. –

+0

Важнейшими факторами являются размер хранилища данных и сложность запросов. –

ответ

2

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

Каждая запись в базе данных означает что-то. Если смысл записи в таблице соединений «Х тренируется в лагере Y школы Z», то вам следует пойти с опцией 2; если вы хотите моделировать значения «Х тренировались в лагере Y» независимо от «Х тренировались в школе Z» и независимо от «Школы Z побежали в лагерь Y», тогда вам следует пойти с опцией 1.

В обоих случаях вам следует предоставить независимые первичные ключи вашим соединениям, а не полагаться на трехстороннюю комбинацию идентификаторов: это упростит вашу жизнь, когда вы реализуете код, который применяет поправки к таблице соединений.

+0

отличный ответ ... и теперь имеет полный смысл. Спасибо! –

+0

Лучший способ описать отношения: CoachX - это текущий тренер для школы. CoachX принимал CampZ 3 года назад и в этом году за их * текущую школу. * Если CoachX переключается на другой учебный год и размещает еще один CampZ ... отношения между предыдущими CampZ и SchoolY для CoachX остаются неповрежденными. –

1

См. Комментарий @Ted Hopp.

Учитывая, что данные (школьные лагеря не происходят много раз в минуту), я думаю, что время обновления меньше приоритета, чем время поиска. Если это так, я бы воспользовался вашей последней опцией, тремя внешними ключами.

Это будет пример star schema.

+0

Я не думал о времени обновления или поиска. Я все еще просто пытался создать базу данных ... спасибо за то, что дал мне понимание другого фактора, который должен быть включен в дизайн базы данных. –

0

Объект Coach выглядит как тот, который должен иметь то, что я обычно называю basket, где он может быть связан с другими объектами во многих отношениях. Вот как я имею в виду:

# The coach model 
CREATE TABLE coach(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    name VARCHAR(20), 
    capacity INT 
) ENGINE=InnoDB; 

# The coach data - who is using the coaches 
CREATE TABLE coach_basket(
    coach_id INT, 
    FOREIGN KEY(coach_id) REFERENCES coach(id), 
    entity_id INT, /* the school or camp id */ 
    entity_type ENUM("School","Camp"), 
    fromdate DATETIME, 
    todate DATETIME 
) ENGINE=InnoDB; 

Итак, теперь вы можете следить за всеми тренер использований, просто введите ENTITY_ID (школу или лагерь идентификатор), а также дату и время, которые они использовали их, каждый раз, когда они используют тренера ,

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

# Store school-camp connections 
CREATE TABLE connections(
    school_id INT, 
    FOREIGN KEY(school_id) REFERENCES school(id), 
    camp_id INT, 
    FOREIGN KEY(camp_id) REFERENCES camp(id) 
) ENGINE=InnoDB; 

Очень просто, просто держать школу и лагерь идентификаторов, так что если вы запросить school_id вас получить много лагерей, с которыми связана школа, и наоборот.

Все, что осталось, это ваши school и camp столы, которые являются моделями (например, столом тренера в верхней части).

+0

Я никогда раньше не видел корзину. Интересный подход. Спасибо. –

Смежные вопросы