Алмазная схема: как (де) нормализовано это? - PullRequest
9 голосов
/ 23 февраля 2012

Предположим, у нас есть следующие объекты:

  • Production Studio
  • Журналист
  • Оператор камеры
  • Видеоматериал

В этом простом мире в продакшн-студии много журналистов и операторов.Каждый журналист принадлежит только к одной студии.То же самое с операторами.Видеозапись производится одним журналистом и одним оператором, причем оба они из одной и той же студии.

Вот мой наивный подход для помещения этой модели в реляционную базу данных:

CREATE TABLE production_studios(
  id                   SERIAL PRIMARY KEY,
  title                TEXT NOT NULL
);

CREATE TABLE journalists(
  id                   SERIAL PRIMARY KEY,
  name                 TEXT NOT NULL,
  prodution_studio_id  INTEGER NOT NULL REFERENCES production_studios
);

CREATE TABLE camera_operators(
  id                   SERIAL PRIMARY KEY,
  name                 TEXT NOT NULL,
  production_studio_id INTEGER NOT NULL REFERENCES production_studios
);

CREATE TABLE news_footages(
  id                   SERIAL PRIMARY KEY,
  description          TEXT NOT NULL,
  journalist_id        INTEGER NOT NULL REFERENCES journalists,
  camera_operator_id   INTEGER NOT NULL REFERENCES camera_operators
);

Эта схема формируетERD прекрасной формы и несколько вопросов.

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

  1. Первый вопрос касается терминологии.: правильно ли утверждать, что эта схема денормализована?Если да, то какая нормальная форма нарушается?Или есть какое-нибудь лучшее название для этой аномалии, например, избыточность между записями, многопутевые отношения и т. Д.?

  2. Как изменить эту схему, чтобы описанная аномалия была невозможна?

И, конечно, я был бы очень признателен за ссылки на статьи, посвященные этой конкретной проблеме.

1 Ответ

3 голосов
/ 23 февраля 2012

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

  • production_studio_id
  • journalist_id
  • camera_operator_id
  • footage_id

и два внешних ключа:

  • journalist_id, production_studio_id, указывающий на таблицу журналиста, и
  • camera_operator, production_studio_id, указывающий на таблицу оператора камеры

Легко.

Или нет. Теперь вы определили в своей модели ER понятие, что само существование оператора камеры или журналиста зависит отстудия, для которой они работают.Это не очень хорошо отражает реальную работу: в этой модели люди не могут сменить работодателя.

Давайте не будем этого делать.

В вашей исходной модели вы путаете человек с ролью, которую они играют (журналист или оператор камеры), и вам не хватает какой-то преходящей сущности, которая фактически отвечает за производство ваших новостных кадров: [съемочная группа для конкретной студии].

Моя модель ER будет выглядеть примерно так:

create table studio
(
  id int not null primary key ,
  title varchar(200) not null ,
)

create table person
(
  id int not null primary key ,
  title varchar(200) not null ,
)

create table team
(
  studio_id          int not null ,
  journalist_id      int not null ,
  camera_operator_id int not null ,

  primary key ( studio_id , journalist_id , camera_operator ) ,

  foreign key ( studio_id          ) references studio ( id ) ,
  foreign key ( journalist_id      ) references person ( id ) ,
  foreign key ( camera_operator_id ) references person ( id ) ,

)

create table footage
(
  studio_id          int not null ,
  journalist_id      int not null ,
  camera_operator_id int not null ,
  id                 int not null ,
  description        varchar(200) not null ,

  primary key ( studio_id , journalist_id , camera_operator_id , id ) ,

  foreign key     ( studio_id , journalist_id , camera_operator_id )
  references team ( studio_id , journalist_id , camera_operator_id ) ,

)

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

Это намного лучше отражает реальный мир и намного более гибко.

Отредактировано длядобавить пример запроса:

Чтобы найти журналистов, работающих в конкретной студии:

select p.*
from studio s
join team   t on t.studio_id = s.id
join person p on p.id        = t.journalist_id
where s.title = 'my desired studio name'

Это даст вам набор людей, которые (или были) связаны со студией вроль журналиста.Однако следует отметить, что в реальном мире люди работают на работодателей в течение определенного периода времени: для правильного моделирования вам необходима дата начала / окончания и вам необходимо квалифицировать запрос с относительным понятием «сейчас».

...