Как избежать избыточности в моей модели базы данных?

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

Вот упрощенная схема: введите здесь описание изображения

Есть ли способ избежать избыточности без удаления таблицы записей?

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


person Quentin Walter    schedule 08.10.2013    source источник
comment
Спасибо @AbstractChaos за исправление схемы.   -  person Quentin Walter    schedule 08.10.2013
comment
Где избыточность (внешние ключи не избыточны, они существуют именно для того, чтобы избежать избыточной информации)? ИМХО, эта структура является единственно жизнеспособной.   -  person RandomSeed    schedule 08.10.2013
comment
@RandomSeed Я согласен с вами, но мне не нравится двойная ссылка Survey_id. явный в таблице записей и неявный в таблице ответов (из question_id).   -  person Quentin Walter    schedule 08.10.2013


Ответы (1)


У вас возникает ощущение, что либо ENTRIES.survey_id, либо QUESTIONS.survey_id избыточны (вероятно, потому, что вы видите, что можно вывести одно или другое через сущность ANSWERS).

На самом деле QUESTIONS и ENTRIES имеют идентифицирующие отношения с SURVEYS (запись или вопрос могут не существовать без соответствующего опроса). Формально говоря, их первичный ключ должен включать ссылку внешнего ключа на родительскую таблицу SURVEYS:

CREATE TABLE SURVEYS (
    survey_id INT NOT NULL,
    PRIMARY KEY (survey_id)
);

CREATE TABLE QUESTIONS (
    question_id INT NOT NULL,
    survey_id INT NOT NULL,
    PRIMARY KEY (question_id, survey_id),
    FOREIGN KEY (survey_id) REFERENCES SURVEYS(survey_id)
);

CREATE TABLE ENTRIES (
    entry_id INT NOT NULL,
    survey_id INT NOT NULL,
    PRIMARY KEY (entry_id, survey_id),
    FOREIGN KEY (survey_id) REFERENCES SURVEYS(survey_id)
);

Как интересное следствие, ваша таблица ANSWERS должна* на самом деле также включать survey_id в свои ссылки на внешние ключи, потому что это поле является частью первичного ключа как QUESTIONS, так и ENTRIES:

CREATE TABLE ANSWERS (
    entry_id INT NOT NULL,
    survey_id INT NOT NULL,
    question_id INT NOT NULL,
    PRIMARY KEY (entry_id, survey_id, question_id),
    FOREIGN KEY (entry_id, survey_id)
        REFERENCES ENTRIES(entry_id, survey_id),
    FOREIGN KEY (question_id, survey_id)
        REFERENCES QUESTIONS(question_id, survey_id)
);

Если это может помочь вам избавиться от ложного впечатления, что одно поле survey_id является избыточным, учтите, что может существовать запись без ответа (например, при создании новой записи). В этой ситуации, очевидно, требуется ENTRIES.survey_id.


* На самом деле это дополнительное поле обязательно для моделирования ограничения "ответ должен относиться к вопросу и записи, которые относятся к одному и тому же опросу".

person RandomSeed    schedule 08.10.2013
comment
Спасибо за Ваш ответ ! Меня беспокоил тот факт, что из ответа я мог (с присоединением) получить доступ к SURVEYS через QUESTIONS и ENTRIES. Я понял, что у меня нет другого выхода. Я не очень люблю гибридный ID. Я предпочитаю работать с уникальным идентификатором; контроллеры сделать проще. Еще раз спасибо за ваше объяснение. - person Quentin Walter; 08.10.2013
comment
@QuentinWalter Я даже не осознавал, что требуется ANSWERS.survey_id, когда впервые написал свой ответ (см. Мое редактирование). Это, однако, прекрасная иллюстрация актуальности этих правил. Вы можете отказаться от кажущихся запутанными составных первичных ключей, но это компромисс с точки зрения производительности, поскольку вам потребуются несколько дополнительных ограничений UNIQUE (и эти ограничения действительно следует считать избыточными). - person RandomSeed; 08.10.2013
comment
Еще раз спасибо за все ваши объяснения. Меня смутили эти составные ПК. Раньше я создавал БД с суррогатными PK и FK (позор мне). Теперь, кажется, я понял, как работает композитный ПК. Можете ли вы высказать свое мнение о полной модели? Некоторые правила: ITEM содержит выбор каждый вопрос, каждый пункт имеет значок. TYPE определяет тип каждого вопроса. Значок может принадлежать категории. Тип [вопрос] может иметь значок. - person Quentin Walter; 12.10.2013
comment
@QuentinWalter Я ошибочно предположил, что отношение идентифицирует если и только если отношение является обязательным, и это вводит в заблуждение. Обратное неверно: обязательное отношение может не быть идентифицирующим. Является ли отношение идентифицирующим, это скорее логическая концепция, чем механическое следствие. Ответ не имеет смысла сам по себе без соответствующего Вопроса. Но Вопрос без Типа все же имеет какое-то значение. Отношения [Вопрос › Тип] и [Элемент › Значок], вероятно, не являются идентифицирующими. - person RandomSeed; 15.10.2013
comment
Спасибо за ваши советы, ваши объяснения были очень ясны. Я несколько раз колебался по поводу этих двух отношений, и поэтому я спросил ваше мнение. Я рад, что вы тоже их заметили. - person Quentin Walter; 16.10.2013