El mejor enfoque de modelado de datos para manejar claves externas redundantes en una base de datos sobre encuestas, preguntas y respuestas


13

Estoy buscando consejos sobre el mejor enfoque de modelado relacional para almacenar encuestas, preguntas y respuestas.

Estoy buscando cuál de los dos enfoques a continuación se ve mejor, o un enfoque alternativo para cualquiera.

Tengo al menos estas entidades:

  • pregunta
  • encuesta
  • persona

Y al menos estas relaciones:

  • Cada encuesta tiene 1 o más preguntas.
  • Cada pregunta puede usarse en 0 o más encuestas.
  • Cada persona puede realizar 0 o más encuestas.

Aquí es donde me encuentro con problemas: cómo modelar las respuestas a las preguntas de la encuesta hechas por una persona.

Aquí hay dos enfoques que he considerado, ninguno de los cuales me parece muy bueno. Los diagramas aquí están muy simplificados para ilustrar el problema.

Enfoque 1: Enfoque 1

Lo que no me gusta de este enfoque:

  • La survey_person_question_responsetabla tiene dos columnas diferentes que se refieren a una encuesta: survey_question_survey_idysurvey_person_survey_id
    • Sería un error tener survey_idreferencias diferentes en una fila para estas dos columnas. La encuesta_pregunta debe ser de la misma encuesta que tomó la persona en encuesta_persona. No puedo ver una buena manera de hacer cumplir esto.
  • Parece que lo que estoy haciendo aquí es hacer una relación entre dos relaciones. Eso me parece mal por alguna razón.

Enfoque 2:

Intente evitar dos FK del enfoque 1 que deberían referirse al mismo valor ... ingrese la descripción de la imagen aquí

Lo que no me gusta de este enfoque:

  • No hay cumplimiento de que los question_idy survey_idFK sean de un survey_questionpar válido
  • No hay cumplimiento de que los survey_idy person_idFK sean de un survey_personpar válido

Cualquier consejo sobre:

  • Si uno de estos enfoques es un enfoque típico
  • Los pros y los contras de uno de estos enfoques sobre el otro
  • Una mejor manera de organizar estos datos por completo

Sería muy apreciado!

Respuestas:


12

Según mi comprensión de sus especificaciones, su entorno empresarial implica una relación ternaria de nivel conceptual . En este sentido, debe definir:

  1. el tipo de relación (o asociación ) entre los tipos de entidad Persona y Encuesta ;
  2. el tipo de relación entre encuesta y pregunta ;
  3. el tipo de relación que establece la conexión entre los dos tipos de relación mencionados anteriormente y, como consecuencia, entre Persona , Encuesta y Pregunta , es decir, Respuesta (un nombre más corto que simplifica la interpretación, desde mi punto de vista).

Por lo tanto, considero que está en el camino correcto con su Enfoque 1 , aunque requiere algunas mejoras pequeñas (pero importantes) para que sea más preciso. Detallaré tales refinamientos y otras consideraciones relevantes en las siguientes secciones.

Reglas del negocio

Expandamos un poco las reglas comerciales aplicables y reformúlelas de la siguiente manera:

  • Una persona se registra en encuestas de cero uno o muchos
  • Una encuesta obtiene el registro de cero-una o muchas personas
  • Una encuesta está integrada por preguntas de uno a muchos
  • Una pregunta integra encuestas de cero uno o muchos
  • Una pregunta recibe cero uno o muchos Respuestas
  • Una respuesta es proporcionada por exactamente una persona en el contexto de exactamente una encuesta

Diagrama IDEF1X expositivo

Luego, he creado el IDEF1X, un diagrama que se presenta en la Figura 1 , que sintetiza las reglas comerciales formuladas anteriormente:

Fig.1 Encuesta simplificada IDEF1X


Una definición de integración para el modelado de información ( IDEF1X ) es una técnica de modelado altamente recomendable que fue establecida como estándar en diciembre de 1993 por el Instituto Nacional de Estándares y Tecnología de los Estados Unidos ( NIST ). Se basa sólidamente en el trabajo teórico escrito por el único fundador del modelo relacional , es decir, el Dr. EF Codd y también en la visión de entidad-relación desarrollada por el Dr. PP Chen .


La relación PersonSurvey

A mi entender, la relación PersonSurvey debe proporcionar un medio de autorización para que una persona pueda participar en una encuesta determinada . De esta manera, una vez que cierta persona se ha registrado en una encuesta específica , él o ella está autorizada a proporcionar respuestas a las preguntas que integran la encuesta respectiva .

La relación de SurveyQuestion

Supongo que la propiedad (o atributo) llamada suvery_question.question_number en su diagrama se usa para representar el Orden de presentación de una instancia de Pregunta dada con respecto a una Encuesta en particular . Como puede ver, he designado propiedades como SurveyQuestion.PresentationOrder , y creo que debe evitar que (i) dos o más valores de Question.QuestionNumber compartan (ii) el mismo valor de PresentationOrder en (iii) la misma ocurrencia de SurveyQuestion .

Para representar esa necesidad, he incluido una CLAVE ALTERNA (AK) compuesta en el cuadro que representa este tipo de entidad, que se compone de la combinación de propiedades ( SurveyNumber, QuestionNumber, PresentationOrder ). Como bien sabe, un AK compuesto puede declararse en un diseño DDL lógico con la ayuda de una restricción ÚNICA de varias columnas (como ejemplifiqué en la SurveyQuestiontabla que forma parte del diseño DDL expositivo expuesto en algunas secciones a continuación).

El tipo de entidad de respuesta

Sí, con el tipo de entidad Respuesta estoy representando una relación entre otras dos relaciones ; que puede parecer extraño a primera vista, pero no hay nada malo con este enfoque, con tal de que (a) representa las características del contexto negocios de interés con precisión y (b) se representa adecuadamente en un diseño de nivel lógico.

Sí, tiene toda la razón, sería un error representar esa parte del escenario en el nivel lógico de abstracción por medio de dos Response.SurveyNumber(o, digamos Response.SurveyId) valores referenciados desde dos columnas diferentes en la misma Responsefila.

Diseño lógico derivado de SQL-DDL

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- As one would expect, you are free to make use of 
-- your preferred (or required) naming conventions.

CREATE TABLE Person (
    PersonId        INT      NOT NULL,
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    BirthDate       DATE     NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Person_PK PRIMARY KEY (PersonId),
    CONSTRAINT Person_AK UNIQUE      (
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    )
);

CREATE TABLE Survey (
    SurveyNumber    INT       NOT NULL,
    Description     CHAR(255) NOT NULL,
    CreatedDateTime DATETIME  NOT NULL,
    --
    CONSTRAINT Survey_PK PRIMARY KEY (SurveyNumber),
    CONSTRAINT Survey_AK UNIQUE      (Description)
);

CREATE TABLE PersonSurvey (
    PersonId           INT      NOT NULL,
    SurveyNumber       INT      NOT NULL,
    RegisteredDateTime DATETIME NOT NULL,
    --
    CONSTRAINT PersonSurvey_PK         PRIMARY KEY (PersonId, SurveyNumber),
    CONSTRAINT PersonSurveyToPerson_FK FOREIGN KEY (PersonId)
        REFERENCES Person (PersonId),
    CONSTRAINT PersonSurveyToSurvey_FK FOREIGN KEY (SurveyNumber)
        REFERENCES Survey (SurveyNumber)
);

CREATE TABLE Question (
    QuestionNumber  INT       NOT NULL,
    Wording         CHAR(255) NOT NULL,
    CreatedDateTime DATETIME  NOT NULL,
    --
    CONSTRAINT Question_PK PRIMARY KEY (QuestionNumber),
    CONSTRAINT Question_AK UNIQUE      (Wording)
);

CREATE TABLE SurveyQuestion (
    SurveyNumber       INT      NOT NULL,
    QuestionNumber     INT      NOT NULL,
    PresentationOrder  TINYINT  NOT NULL,
    IsMandatory        BIT      NOT NULL,
    IntegratedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT SurveyQuestion_PK PRIMARY KEY (SurveyNumber, QuestionNumber),
    CONSTRAINT SurveyQuestion_AK UNIQUE      (
        QuestionNumber,
        SurveyNumber,
        PresentationOrder
    ),
    CONSTRAINT SurveyQuestionToSurvey_FK   FOREIGN KEY (SurveyNumber)
        REFERENCES Survey   (SurveyNumber),
    CONSTRAINT SurveyQuestionToQuestion_FK FOREIGN KEY (QuestionNumber)
        REFERENCES Question (QuestionNumber)
);

CREATE TABLE Response (
    SurveyNumber     INT      NOT NULL,
    QuestionNumber   INT      NOT NULL,
    PersonId         INT      NOT NULL,
    Content          TEXT     NOT NULL,
    ProvidedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Response_PK                 PRIMARY KEY (SurveyNumber, QuestionNumber, PersonId),
    CONSTRAINT ResponseToPersonSurvey_FK   FOREIGN KEY (PersonId, SurveyNumber)
        REFERENCES PersonSurvey   (PersonId, SurveyNumber),
    CONSTRAINT ResponseToSurveyQuestion_FK FOREIGN KEY (SurveyNumber, QuestionNumber)
        REFERENCES SurveyQuestion (SurveyNumber, QuestionNumber)
);

Dos teclas extranjeras compuestas en la Responsemesa

Este es, probablemente, el punto más importante para discutir: las referencias hechas desde una Responsefila dada a

  1. SurveyQuestion.SurveyNumbery
  2. SurveyPerson.SurveyNumber

debe tener valores coincidentes . En lo que a mí respecta, la mejor opción para hacer cumplir esta condición de manera declarativa es hacer uso de dos CLAVES EXTRANJERAS compuestas (FK).

Como se muestra en el diseño DDL, el primer FK hace referencia a la PersonSurveytabla PRIMARY KEY (PK), es decir (PersonId, SurveyNumber), y está conformado por las columnas Response.PersonIdy Response.SurveyNumber.

El segundo FK apunta a la SurveyQuestiontabla PK, es decir (SurveyNumber, QuestionNumber), y, en consecuencia, está formado por las columnas Response.SurveyNumbery Response.QuestionNumber.

De esta manera, la Response.SurveyNumbercolumna es bastante instrumental ya que se usa como parte de una referencia FK en dos restricciones diferentes.

Con este método, uno garantiza la integridad referencial garantizada por el sistema de gestión de la base de datos de

  • (a) Responsea la PersonSurvey;
  • (b) Responsea la SurveyQuestion; y
  • (c) cada una de las tablas que representan un tipo de entidad asociativa a las tablas que representan tipos de entidad independientes, a saber Person, Surveyy Question.

Datos derivados para evitar anomalías de actualización

He notado en su diagrama dos elementos que valoro mencionar. Estos elementos están relacionados con dos PersonSurveycolumnas que pueden (deberían) derivarse .

En ese sentido, puede derivar el PersonSurvey.IsStarteddato al consultar si una Personocurrencia dada ha proporcionado uno o más Responsespara Questionsintegrar una exacta a Surveytravés de la SurveyQuestiontabla.

Y también puede obtener el PersonSurvey.IsCompletedpunto de datos determinando si una Personinstancia dada ha proporcionado un valor Responsea todos los Questionsque mantienen un valor de 'VERDADERO' en la IsMandatorycolumna en una SurveyQuestionfila específica .

Mediante la derivación de estos valores, está evitando algunas anomalías de actualización que eventualmente habrían surgido en caso de que haya mantenido dichos valores en la SurveyQuestioncolumna.

Importante consideración

Como @Dave señala correctamente en su comentario, si enfrenta un requisito futuro que exige la gestión de diferentes tipos de respuestas que implican la gestión de fechas, valores numéricos, opción múltiple y otros aspectos posibles, tendrá que ampliar este diseño de base de datos.


1
¡Guau, esto respondió perfectamente la pregunta en mi cabeza y luego me enseñó más! Dado que los comentarios deberían sugerir mejoras: fue un poco confuso que las teclas terminaran con ambos IDy Number, pero por lo demás, esto es fantástico. Gracias.
Zach Mierzejewski

@Zach De nada, me alegra que la publicación te haya ayudado. Gracias por los comentarios, se requieren decididamente algunas mejoras.
MDCCL

1

Esta es una razón por la que no me gusta prefijar columnas cuando las migro como claves foráneas. En su primer caso, la herramienta de modelado puede obligarlo a prefijar una de las survey_idcolumnas de la survey_person_question_responsetabla. Es posible que pueda ajustar esto después de que se establezca la relación.

Si es necesario, elimine el campo de identificación de encuesta redundante cuando cree el modelo físico donde no necesita la columna duplicada. Como ha identificado, ambos modelos tienen problemas, pero creo que el primer modelo es mejor en general.


Gracias por la información: colapsé a 1 columna en el modelo físico que hace cumplir todo lo que quería.
código muerto el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.