2015-01-03 1 views
1

У меня есть 2 таблицы, которые я пытаюсь нормализовать. Проблема в том, что я не хочу создавать таблицу с новыми полями, хотя, возможно, работает таблица ссылок. Каков самый элегантный способ сообщить, что запись «Nintendo» - это как разработчик, так и разработчик? Я не хочу дублировать «Nintendo». Я думаю, что отношения «многие ко многим» могут быть ключевыми.Элегантная нормализация без добавления полей, дополнительная таблица. Лучшие отношения

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

Вот 2 таблицы я пытаюсь нормализовать:

enter image description here

Ниже решение, которое я попробовал (не нравится): enter image description here

+1

Я не уверен, что понятие «элегантности» имеет место в нормализации баз данных. Реляционная модель основана на математике, а не на искусстве; есть что-то, называемое логикой предиката первого порядка, в которой мало кто интересуется, но короткая версия: у вас есть отношения «многие ко многим», нравится вам это или нет. Единственный способ выразить это, используя нормализованные таблицы, - это таблица ссылок, полная остановка. – Air

+1

@AirThomas & klandshome: Я согласен с RM и точностью, но здесь нет нормализации и не существует отношения «многие ко многим», кроме одного выводимого из двух таблиц, в котором выражаются отношения «developer [id] - это компания с именем [имя]», и «издателем [id] является компания с именем [name]». – philipxy

+1

Это не имеет никакого отношения к нормализации, и нет необходимости изменять ваши таблицы. См. Мой обновленный ответ. – philipxy

ответ

1

Я думаю, что вы хотите что-то например:

Game_Company 
ID Name 
1 Retro Studios 
2 HAL Laboratories 
3 Nintendo 
... 

Company_Role 
ID Name 
1 Developer 
2 Publisher 
... 

Game_Company_Role 
CompanyID RoleID 
     1   1 
     2   1 
     3   1 
     3   2 
... 

Чтобы получить список всех компаний, имеющих роль «Разработчик»:

SELECT gc.name 
FROM Game_Company gc JOIN Game_Company_Role gcr ON gcr.CompanyID=gc.ID 
WHERE gcr.RoleID = 1 
+1

Хороший совет @AirThomas; сделанный. –

+0

Хм. Итак, мое решение было правильным и единственным способом? Мне нужно создать таблицу «роль»? Нет способа заставить его работать с таблицей разработчика и издателя? –

+0

Также может быть полем «Тип» под Company_Role вместо «Name»? –

0

Это немного общий подход к проблеме, это может представлять интерес. Как отметил @Dour High Arch в своем решении, разработчик и издатель - это просто роли для «вечеринки». Каждая часть имеет 0,1 или более ролей с данным продуктом, а роли могут перекрываться. Это хорошо и плохо. Например, продукт может быть разработан 5 разработчиками, но опубликован не более чем 1 издателем. Я решил ввести serial_id как сгенерированный системой ПК, но это необязательно. Вы можете использовать 3FK как ПК, а не пользователь serial_id.

Обратите внимание, что наличие стороны в качестве обобщения различных типов объектов не всегда хорошо, так как 1 или более столбцов должны быть установлены как необязательные, если это не является общим для всех сторон, однако это очень распространено в реальных Приложения.

конвенция:

name_PK = Первичный ключ,

name_FK = Внешний ключ

pic

+0

Какую программу вы использовали для этого UML? –

+1

Есть много хороших инструментов для ERD и UML, я использовал Gliffy по адресу: https://www.gliffy.com – NoChance

+1

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

2

Там нет ничего плохого с двумя столами.

На самом деле все, что вам нужно, это

developer(name) -- company [name] is a developer 
publisher(name) -- company [name] is a publisher 

Ваши изменения не имеют ничего общего с нормализацией. Нормализация никогда не создает новые имена столбцов. «Я не хочу, чтобы« Nintendo »дублировался, ошибочно. По сути, нет ничего неправильного со значениями, появляющимися во многих местах. См. Ответы от sqlvogel & себя here.

НО: В зависимости от того, что означает, что строка находится в одной из ваших таблиц, может быть лучший дизайн для уменьшения ошибок, поскольку значения двух таблиц могут быть «ограниченными», т.е. зависят друг от друга. То, что имеет какое-то отношение к «избыточность», но касается ограничений и не требует нормализации. И для того, чтобы обратиться к нему, вы должны сказать нам, когда строка входит в каждую таблицу, основанную на мировой ситуации.

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

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

Если вы хотите, чтобы новая таблица для «[id] идентифицировала компанию с именем [name] with ...», то это случай разработчиков и издателей как подтипы компании супертипа. Поиск в подтипах базы данных. См. this answer. Затем вы должны использовать идентификатор компании вместо имени для идентификации компаний. Затем вы могли бы также упростить (!), Используя идентификатор компании как единственный столбец в разработчиках и издателях таблиц, а также везде, а не разработчик_ид и publisher_id.

«Резервирование» не относится к значениям, появляющимся в нескольких местах. Речь идет о нескольких строках, в которых говорится о приложении. При использовании такого дизайна существуют две основные проблемы: говорить о некоторых вещах, связанных с несколькими строками (в то время как нормализованная версия включает только одну строку); и нет никакого способа сказать только одну из вещей за раз (с которой может помочь нормализация). Если вы создадите два разных независимых утверждения о Nintendo, вам понадобятся две таблицы и Nintendo, упомянутые в каждом из них. Строки Re, содержащие заявления о приложении, см. this. (И искать другие ответы на «утверждение» или «критерий» таблицы). Нормализация помогает, потому что она заменяет таблицы, строки которых содержат элементы формы «... И ...» другими таблицами, в которых указано «...» отдельно. См. this и this. (Обычно ошибочно считается, что включение или включение исключает несколько похожих столбцов, избегая столбцов, значения которых имеют повторяющуюся структуру и/или заменяют строки идентификаторами, но хотя это могут быть хорошие дизайнерские идеи, они не нормализуются .)


В комментариях, чат и еще один ответ вы дали эту отправную точку:

enter image description here

Вот простейший дизайн. (Я предполагаю, что названия игр не являются уникальными, так что вам нужно game_ids.)

-- game [game_id] with title [title] released on [release_date] is rated [rating] 
game(game_id,title,release_date,rating) 
game_developer(game_id,name) -- game [game_id] is developed by company [name] 
game_publisher(game_id,name) -- game [game_id] is published by company [name] 
game_platform(game_id,name) -- game [game_id] is on platform [name] 

Только если вы хотите отдельный список компаний, с тем, что компания может существовать без разработки и публикации и/или может иметь свои собственные данные вам нужно добавить:

company(name,...) -- [name] identifies a company 

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

developer(name,...) -- developer [name] has ... 
publisher(name,...) -- publisher [name] has ... 

соответствующие внешние ключи различных опций straightward.

Ни одна из ваших версий _id s.Ваши версии 2 & 3 не будут работать, потому что они не говорят, какие компании разрабатывают игру или какие компании публикуют игру. Вам не нужны роли, но если у вас есть они (Verison 2), тогда вам понадобится таблица «игра [game_id] имеет компанию [name] as [role]». В противном случае (для версии 3) вам нужны таблицы для «[game_id], разработанного компанией [name]», а «game [game_id] публикуется компанией [name]». Где бы вы ни отличались от моих проектов, спросите себя , почему у у вас есть дополнительная структура и почему вы можете обойтись без нее и (возможно), почему вы так или иначе захотите этого.

+1

Нет «нового имени столбца», имя было изменено, чтобы избежать использования зарезервированного слова SQL «TYPE». проблема с «значениями, появляющимися в нескольких местах», если они представляют одно и то же значение. Это базовая первая нормальная форма и не имеет ничего общего с «занятым пространством»; @klansdhome сказал нам, что две «Nintendo» - это одна и та же компания, полагая, что в двух таблицах открывается возможность аномалии обновления, если вы меняете одно, а не другое. –

+2

Я не сказал, что ваш дизайн сделал; «решение» пользователя вводит «тип». Я не говорил, что дубликаты никогда не были лишними, я сказал, что они не обязательно лишние. (Как с идентификаторами в * вашей собственной таблице *.) Я не сказал, что нормализованное пространство сохраняется; Я сказал, заменяя строки идентификаторами, и таблица поиска может и я сказал, что это * не * нормализация. «Это базовый 1NF» неверен; узнайте о нормализации, связанной с заменой таблиц другими, перераспределяя столбцы, чтобы новые таблицы присоединились к старому. В двух таблицах нет аномалий обновления; узнайте, что это такое. Также, пожалуйста, внимательно прочитайте мой ответ. – philipxy

+0

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

0

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

правила заключаются в следующем:

  • 1 игра может иметь 1 или много разработчиков и 1 разработчик может иметь 1 или много игр.
  • 1 игра может иметь 1 или много издателей и 1 издатель может иметь 1 или много игр.
  • 1 игра может иметь 1 или много платформ и 1 платформа может иметь 1 или много игр.

enter image description here

Version 1

Я оставил 2 "Нинтендо" записи в красном цвете. Согласно исследованиям и реализации, это не технически избыточные данные. См. Мои комментарии по запросу philipxy. Это выглядит просто и элегантно. 4 таблицы с отношением «многие ко многим».

enter image description here

Вот диаграмма отношения (4 таблицы и 3 стола ссылка):

enter image description here

Verison 2

версия 1 "повторяет" "Нинтендо", но версия 2 вместо этого используется таблица «Компания». Сравните две разные версии. Каков правильный путь?

enter image description here

Версия 3

Вот подтипов philipxy говорил. Как эта версия?

enter image description here

+0

Вы правы. Но что вы думаете о версии 2? –

+0

Могу ли я увидеть визуализацию того, что вы подразумеваете в точности не используя атрибут роли? Немного смущен. –

+0

Попытка визуализации таблицы компаний сейчас. Итак, мы держим таблицу компаний? Вы можете это сделать? Или мы храним dev и pub .. что-то непонятно –

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

  • Нет связанных вопросов^_^