Вопрос моделирования "один ко многим"

Как лучше всего смоделировать следующие ...

Предположим, у меня есть два объекта: Agency и Publisher, и оба имеют отношение "1 к n" с Employee. Это истинное отношение «1 к n», поскольку каждый Employee может работать только для одного Agency или одного Publisher. Предположим далее, что я не могу ввести супертип (например, Employer), который поддерживает отношение 1 к n.

Я предпочитаю иметь внешний ключ в Employee, который может ссылаться на первичный ключ Agency или Publisher (все мои первичные ключи - это 64-битные идентификаторы, уникальные для всей базы данных). Однако теперь я не смогу отобразить двунаправленную ассоциацию, не указав в Employee, является ли это отношением Agency или Publisher.

Другой вариант - использовать две таблицы AgencyEmployee и PublisherEmployee, которые затем можно связать как традиционные двунаправленные ассоциации «1 к n».

Что вы считаете оптимальным в этой ситуации?

ОБНОВЛЕНИЕ: Спасибо за отличные ответы за такой короткий промежуток времени! Что вы думаете о следующем решении: внешние ключи в Employee для Agency и Publisher, например, agency_id и publisher_id?


person Tony the Pony    schedule 11.03.2009    source источник


Ответы (6)


Лучшей практикой, вероятно, было бы введение класса «Работодатель».

С другой стороны, разделение сотрудника на AgencyEmployee и PublisherEmployee было бы плохим делом.

Если бы о представлении работодателя не могло быть и речи, я бы указал тип работодателя (агентство или издатель) в поле «Сотрудник».

Ответ на обновленный вопрос:

Это вариант, но работодатель_тип лучше, потому что:

  1. Возможно, вы захотите добавить другие типы работодателей в будущем
  2. В каждой строке таблицы «Сотрудники» будет пустое поле.
person Can Berk Güder    schedule 11.03.2009
comment
Я согласен с передовой практикой и вызовами Bad Thing, но я думаю, что с точки зрения нормализации было бы лучше иметь третью таблицу с EmployeeID как PK, EmployerID и EmployerType. - person Harper Shelby; 11.03.2009
comment
@Harper: Это правильно, но с прагматической точки зрения это означает еще одно соединение (и первичный ключ с несколькими столбцами). - person Can Berk Güder; 11.03.2009

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

person duffymo    schedule 11.03.2009

Я использовал такой подход:

Employee.EmployerType ("АГЕНТСТВО" или "ИЗДАТЕЛЬ")

Employee.EmployerID (AgencyID или PublisherID)

Он работает нормально, но вам нужен оператор case во многих ваших SQL. Также, если вы используете ORM, вы теряете отношения FK.

Я перемещаю большую часть своего кода в отношения n: m, чтобы воспользоваться нашей поддержкой ORM FK.

person Jamison    schedule 11.03.2009

Очевидно, что предпочтительнее будет организация-работодатель, но в противном случае ...

Наличие таблиц AgencyEmployee и PublisherEmployee означает, что будет сложно определить, принадлежит ли сотрудник к той или иной категории.

Поэтому вместо этого я бы добавил столбец EmployerType в таблицу «Сотрудники»; он добавляет немного дополнительной сложности вашим последующим SQL-запросам, но работает в рамках установленных вами ограничений.

Ради интереса, почему вы могли бы добавить таблицы AgencyEmployee и PublisherEmployee, но не добавить таблицу Employer? Просто любопытно...

person CJM    schedule 11.03.2009

Оценка +1 для Джана Берка Гюдера.

Технически введение супертипа «Работодатель» означает, что вы вводите отношение «Работодатель» со всеми атрибутами, общими для Агентства и Издателя, «Специфическое для Агентства» отношение (не знаю, как его назвать) с ключом «Работодатель» и всеми атрибутами, зависящими от Агентства, а также для ключа «Работодатель» как внешнего key, затем Agency как запрос или представление, которое просто соединяет AgencySpecific с работодателем, а также для издателя.

Распределение данных об агентстве и издателе по двум таблицам, которые вы должны объединять каждый раз, может быть немного обременительным, но альтернатива - написать большую часть ваших запросов, связанных с сотрудниками, дважды, один раз с помощью агентства и один раз с помощью издателя, а затем вручную. их союзы, чтобы объединить результаты. (Я не видел построителя запросов, который помогал бы с такими базовыми вещами.) Мне пришлось сделать это для проекта, в котором использовался подход «без супертипов», и я не хочу делать это снова.

Кстати, троичные отношения и даже отношения n-to-n не являются хорошей практикой проектирования, если вы спросите меня. Использование только функций (т.е. 1-к-n и 1-к-1), например. ограничения стало намного проще сформулировать.

person reinierpost    schedule 11.03.2009

Лично я предпочитаю иметь таблицу, которую, как вы прямо предполагаете, нельзя использовать (Супертип агентства и издателя; работодатель)

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

Мое последнее предпочтение было бы похоже на ваше предложение: иметь одну таблицу для AgencyEmployees и одну для PublisherEmployees. Но я бы выделил это на один шаг дальше ...

Table1: Agency              (id, name, etc)
Table2: Publisher           (id, name, etc)
Table3: Employee            (id, name, etc)
Table4: AgencyEmployees     (agency_id, employee_id)
Table5: PublisherEmployees  (publisher_id, employee_id)


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

Table1: Agency              (id, name, etc)
Table2: Publisher           (id, name, etc)
Table3: Employee            (id, name, etc)
Table4: AgencyEmployees     (agency_id,    employee_id, start_date, leave_date)
Table5: PublisherEmployees  (publisher_id, employee_id, start_date, leave_date)

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

person MatBailie    schedule 11.03.2009