проектирование реляционных баз данных (нормализация отображений «многие ко многим») - PullRequest
2 голосов
/ 19 ноября 2010

Ниже приведен аналог (и упрощенный) пример вопроса о дизайне, с которым я сталкиваюсь:

Предположим, у вас есть ученики, классы и оценки.Студенты могут быть в разных классах.В каждом классе много разных учеников.И каждая пара (студент, класс) имеет один класс.

Должен ли я расположить базу данных (базу данных mysql) следующим образом:

Вариант 1)

students table - (student_id, student_name)
classes table - (class_id, class_name)
students_classes table - (student_class_id, student_id, class_id)
grades table - (student_class_id, grade)

Вариант 2)

students table - (student_id, student_name)
classes table - (class_id, class_name)
grades table - (student_id, class_id, grade)

Или это должно быть задумано как-то еще?Вариант 2 кажется проще сейчас, но в будущем мне могут понадобиться другие статистические данные, связанные с каждой парой (student_id, class_id) (в этом случае вариант 1 кажется немного лучше? Вариант 1 все еще чувствует себя немного сложнее).

Что вы рекомендуете?Спасибо.

Ответы [ 5 ]

3 голосов
/ 19 ноября 2010

Вариант 3)

students table - (student_id, student_name)
classes table - (class_id, class_name)
students_classes table - (student_class_id, student_id, class_id, grade)

Оценка является атрибутом ученического класса.

Если у Сорта нет возможности стать полноценной сущностью. В каком случае:

Вариант 4)

students table - (student_id, student_name)
classes table - (class_id, class_name)
students_classes table - (student_class_id, student_id, class_id)
grades table - (grade_id, grade, student_class_id)
3 голосов
/ 19 ноября 2010

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

В варианте 1, Students_classes не имеет никакой цели, кроме наличия суррогатного ключа.Отредактируйте, увидев другие ответы:

  • 2NF: оценка (не ключ) зависит исключительно от учащегося / класса (ключ)
  • 3NF: не применяется.У вас нет неключевого ключа для неключевых зависимостей
  • BCNF: не применяется, у вас есть только один ключ-кандидат
1 голос
/ 28 ноября 2010

Вариант 2 верен, за исключением того, что он должен называться student_class, отражая его функцию n :: n или Enrollment как объект.(student_id, class_id) - это PK.

Grade (как вы это показали) - это зависимость 1 :: 1 от этого составного ключа (не от одного или другого элемента) и ни от чего другого, поэтому онявляется атрибутом student_class.

И, следовательно, student_class в 3NF.

Если люди не начали с того, что вслепую вставляли Id столбцы на все, что двигалось, когда выс вариантом 1, они смогут лучше понимать данные и, следовательно, лучше нормализовать.Тот (Id столбец в Варианте 1 как отправная точка) мешал вашей интуиции, что (student_id, class_id) был Идентификатором;дополнительный столбец Id с дополнительным индексом не требуется.Затем, когда вы приступили к оценке grade, его зависимость от этого PK очевидна.

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

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

Вот > Модель данных для колледжа <</strong> из недавнего задания, упрощенная версия.

> Обозначение IDEF1X<</strong> для тех, кому необходимо пояснение символов.

  • Обратите внимание, что требуется только один суррогатный ключ.

    • Это потому, что вальтернативой (LastName + FirstName + Initials_BirthDate + BithDate) будет Person PK, и он будет переноситься как FK в 5 дочерних / внучатых таблицах, что составляет 81 байт, и это не имеет смысла.
      .
  • Посмотрите, сможете ли вы оценить, что Идентификаторы (сплошные линии) доведены до детей и внуков;они имеют и передают значение

  • Было бы глупо добавлять суррогатные ключи для TeacherId, StudentId, StaffId, когда у нас есть совершенно хороший PersonId, который является внешним ключом и уже уникальным.(Столбцы названы таковыми для обозначения их ролей.)

  • Все бизнес-правила были реализованы в DDL: ограничения FK;Проверьте ограничения;Правила.

    • В комнате есть составной ключ из 4 колонок;Предложение имеет 3-х столбный составной ключ;оба вместе исключают двойное бронирование.

    • PK предложения и PK ученика вместе образуют PK для зачисления (идентичны этому Вопросу; PK состоят из разных столбцов, вот и все).

0 голосов
/ 19 ноября 2010

Все зависит, правда. Вариант 1, вероятно, самый надежный способ сделать это приложение; Вариант 2 может помочь вам быстрее на этой итерации. Будет ли изменение в варианте 2 -> 1 таким болезненным в будущем? Насколько вы уверены, что вам понадобится такая дополнительная гибкость?

Я бы порекомендовал просто перейти к варианту 1. Запросы не будут намного сложнее, и если вы используете ORM (например, ActiveRecord для Rails среди многих), тогда разница практически равна нулю.

0 голосов
/ 19 ноября 2010

Я болею за обычную форму, где у вас есть отдельные таблицы учеников, классов и классов, и вы связываете их со многими таблицами, такими как ClassStudent и GradeClass.

Но этозависит от того, как вы хотите сохранить его в будущем.В конечном итоге все сводится к расширению и удобству обслуживания в будущем.Вот почему я предпочитаю 3NF.

РЕДАКТИРОВАТЬ

Ответ Axn намного лучше, чем мой.

...