Схема, когда пользователи могут определять поля - PullRequest
5 голосов
/ 09 января 2009

Приветствую укладчиков,

Я пытаюсь найти лучшую схему базы данных для приложения, которое позволяет пользователям создавать опросы и представлять их публике. Существует множество «стандартных» демографических полей, которые будут включать большинство опросов (но не все), такие как «Имя», «Фамилия» и т. Д. И, конечно, пользователи могут создавать неограниченное количество «пользовательских» вопросов.

Первое, о чем я подумал, примерно так:

Survey
  ID
  SurveyName

SurveyQuestions
  SurveyID
  Question

Responses
  SurveyID
  SubmitTime

ResponseAnswers
  SurveyID
  Question
  Answer

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

Улучшение было бы включать в таблицу ответов столько полей, сколько я могу придумать заранее:

Responses
  SurveyID
  SubmitTime
  FirstName
  LastName
  Birthdate
  [...]

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

Но, похоже, это немного усложнит код. Теперь, чтобы увидеть, какие вопросы задаются в опросе, я должен проверить, какие общие поля ответов включены (используя, я думаю, битовое поле в Survey) И что находится в таблице SurveyQuestions. И мне нужно беспокоиться об особых случаях, например, если кто-то пытается создать «пользовательский» вопрос, который дублирует «общий» вопрос в таблице ответов.

Это лучшее, что я могу сделать? Я что-то упустил?

Ответы [ 4 ]

5 голосов
/ 09 января 2009

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

Кроме того, многие (возможно, большинство) результатов опроса просматриваются только периодически и небольшим числом людей (организаторами мероприятий, администраторами и т. Д.), Поэтому вы не будете постоянно запрашивать базу данных для всех результатов. И даже если бы вы были, производительность будет в порядке. В любом случае, вы, возможно, все равно разберетесь с результатами.

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

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

    surveys
      survey_id (index)
      title

    questions
      question_id (index, auto increment)
      survey_id (link to surveys->survey_id)
      question

    responses
      response_id (index, auto increment)
      survey_id (link to surveys->survey_id)
      submit_time

    answers
      answer_id (index, auto increment)
      question_id (link to questions-question_id)
      answer
1 голос
/ 09 января 2009

Единственное изменение, которое может помочь, а может и не помочь упростить ситуацию, - это не связывать ResponseAnswers обратно с SurveyID. Вместо этого создайте идентификатор для ответа и для каждого вопроса, и пусть ваша таблица ResponseAnswers содержит поля ResponseID, QuestionID, Answer. Хотя это потребует сохранения уникальных идентификаторов для каждого устройства, это поможет немного нормализовать ситуацию. Ответы на ответы не нужно связывать с опросом, на который они отвечали, только на конкретный вопрос, на который они отвечают, и с информацией об ответах, с которой они связаны.

1 голос
/ 09 января 2009

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

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

0 голосов
/ 09 января 2009

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

Пара незначительных отличий:

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

  • Был набор вопросов, которые были прикреплены к опросам, поэтому один вопрос можно было использовать в нескольких опросах и анализировать независимо от опроса, в котором он появился.

  • Обработка различных типов вопросов стала интересной - у нас была шкала 1-3 (например, хуже / одинаково / лучше), шкала 1-5 (очень плохо, плохо, хорошо, хорошо, очень хорошо), Да / Нет и комментарии.

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

Чтобы упростить запросы, вы, вероятно, могли бы создать функцию для возврата ответа на основе идентификатора опроса и идентификатора вопроса.

...