Meilleure approche de modélisation des données pour gérer les clés étrangères redondantes dans une base de données sur les enquêtes, les questions et les réponses

13

Je recherche des conseils sur la meilleure approche de modélisation relationnelle pour stocker les enquêtes, les questions et les réponses.

Je cherche laquelle des deux approches ci-dessous semble la meilleure, ou une approche alternative à l'une ou l'autre.

J'ai au moins ces entités:

  • question
  • enquête
  • la personne

Et au moins ces relations:

  • Chaque enquête comporte une ou plusieurs questions.
  • Chaque question peut être utilisée dans 0 enquête ou plus.
  • Chaque personne peut participer à 0 ou plusieurs sondages.

Voici où je rencontre des problèmes: comment modéliser les réponses aux questions du sondage faites par une personne.

Voici deux approches que j'ai envisagées, dont aucune ne me semble très bonne. Les diagrammes ici sont grandement simplifiés pour illustrer le problème.

Approche 1: Approche 1

Ce que je n'aime pas dans cette approche:

  • Le survey_person_question_responsetableau comporte deux colonnes différentes qui font référence à une enquête: survey_question_survey_idetsurvey_person_survey_id
    • Ce serait une erreur d'avoir survey_iddes références différentes dans une ligne pour ces deux colonnes. L'enquête_question doit provenir de la même enquête que la personne a répondu à enquête_personne. Je ne vois pas de bonne façon de faire respecter cela.
  • Il semble que ce que je fais ici, c'est d'établir une relation entre deux relations. Cela me fait du tort pour une raison quelconque.

Approche 2:

Essayez d'éviter deux FK de l'approche 1 qui devraient se référer à la même valeur ... entrez la description de l'image ici

Ce que je n'aime pas dans cette approche:

  • Il n'y a aucune application que les question_idet survey_idFK sont d'une survey_questionpaire valide
  • Il n'y a aucune application que les survey_idet person_idFK sont d'une survey_personpaire valide

Tout conseil sur:

  • Si l'une de ces approches est une approche typique
  • Les avantages et les inconvénients de l'une de ces approches par rapport à l'autre
  • Une meilleure façon d'organiser entièrement ces données

Serait grandement apprécié!

code mort
la source

Réponses:

12

Selon ma compréhension de vos spécifications, votre environnement commercial implique une relation ternaire au niveau conceptuel . À cet égard, vous devez définir:

  1. le type de relation (ou d' association ) entre les types d'entité Personne et Enquête ;
  2. le type de relation entre l' enquête et la question ;
  3. le type de relation qui établit le lien entre les deux types de relation susmentionnés et, par conséquent, entre la personne , l' enquête et la question , c'est-à-dire la réponse (un nom plus court qui simplifie l'interprétation, de mon point de vue).

Donc, je considère que vous êtes sur la bonne voie avec votre approche 1 , même si elle nécessite quelques petits raffinements (pourtant importants) pour la rendre plus précise. Je détaillerai ces améliorations et d'autres considérations pertinentes dans les sections suivantes.

Règles métier

Développons un peu les règles métier applicables et reformulons-les de la manière suivante:

  • Une personne s'inscrit à zéro-un ou plusieurs sondages
  • Une enquête obtient l'enregistrement de zéro ou une personne
  • Une enquête est intégrée par un-à-plusieurs questions
  • Une question intègre zéro-un-ou-plusieurs sondages
  • Une question reçoit zéro ou une ou plusieurs réponses
  • Une réponse est fournie par une seule personne dans le contexte d'une seule enquête

Diagramme expositoire IDEF1X

Ensuite, j'ai créé l'IDEF1X, un diagramme présenté dans la figure 1 , qui synthétise les règles métier formulées ci-dessus:

Fig.1 Enquête simplifiée IDEF1X


Une définition d'intégration pour la modélisation de l'information ( IDEF1X ) est une technique de modélisation hautement recommandable qui a été établie en tant que norme en décembre 1993 par le National Institute of Standards and Technology ( NIST )des États-Unis. Il est solidement basé sur des travaux théoriques rédigés par le seul fondateur du modèle relationnel , c'est-à-dire le Dr EF Codd, ainsi que sur la vision des relations d'entité développée par le Dr PP Chen .


La relation PersonSurvey

À mon avis, la relation PersonSurvey doit fournir un moyen d'autorisation pour qu'une personne puisse participer à une enquête donnée . De cette façon, une fois qu'une certaine personne a été inscrite à un sondage spécifique , elle est autorisée à fournir des réponses aux questions qui intègrent le sondage respectif .

La relation SurveyQuestion

Je suppose que la propriété (ou attribut) appelée suvery_question.question_number dans votre diagramme est utilisée pour représenter l' ordre de présentation d'une instance de question donnée par rapport à une enquête particulière . Comme vous pouvez le voir, j'ai désigné une propriété telle que SurveyQuestion.PresentationOrder , et je pense que vous devriez empêcher que (i) deux ou plusieurs valeurs Question.QuestionNumber partagent (ii) la même valeur PresentationOrder dans (iii) la même occurrence SurveyQuestion .

Pour représenter ce besoin, j'ai inclus une clé ALTERNATE composite (AK) dans la boîte représentant ce type d'entité, qui comprend la combinaison de propriétés ( SurveyNumber, QuestionNumber, PresentationOrder ). Comme vous le savez bien, un AK composite peut être déclaré dans une conception DDL logique à l'aide d'une contrainte UNIQUE à plusieurs colonnes (comme je l'ai illustré dans le SurveyQuestiontableau qui fait partie de la disposition DDL expositoire exposée quelques sections ci-dessous).

Le type d'entité Response

Oui, avec le type d'entité Response , je représente une relation entre deux autres relations ; cela peut sembler gênant à première vue, mais il n'y a rien de mal à cette approche, tant qu'elle (a) représente avec précision les caractéristiques du contexte commercial d'intérêt et (b) est correctement représentée dans une disposition de niveau logique.

Oui, vous avez tout à fait raison, ce serait une erreur de représenter cette partie du scénario au niveau logique de l'abstraction au moyen de deux Response.SurveyNumber(ou, disons Response.SurveyId) valeurs référencées à partir de deux colonnes différentes dans la même Responseligne.

Disposition logique SQL-DDL dérivée

-- 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)
);

Deux clés étrangères composites dans le Responsetableau

C’est probablement le point le plus important à discuter: les références faites à partir d’une Responseligne

  1. SurveyQuestion.SurveyNumber, et
  2. SurveyPerson.SurveyNumber

doit avoir des valeurs correspondantes . En ce qui me concerne, la meilleure option pour appliquer cette condition de manière déclarative est d'utiliser deux clés étrangères composites (FK).

Comme le montre la conception DDL, le premier FK fait référence à la PersonSurveytable KEY PRIMARY (PK), c'est-à-dire (PersonId, SurveyNumber), et est conforme aux colonnes Response.PersonIdet Response.SurveyNumber.

Le second FK pointe vers la SurveyQuestiontable PK, c'est-à-dire (SurveyNumber, QuestionNumber), et est, par conséquent, composé des colonnes Response.SurveyNumberet Response.QuestionNumber.

De cette façon, la Response.SurveyNumbercolonne est assez instrumentale car elle est utilisée dans le cadre d'une référence FK dans deux contraintes différentes.

Avec cette méthode, on assure garantie système de gestion de base de données l' intégrité référentielle de

  • a) Responseau PersonSurvey;
  • b) Responseau SurveyQuestion; et
  • (c) chacune des tables représentant un type d'entité associative aux tables représentant des types d'entité indépendants, à savoir Person, Surveyet Question.

Données dérivées pour éviter les anomalies de mise à jour

J'ai remarqué dans votre diagramme deux éléments qui, selon moi, méritent d'être mentionnés. Ces éléments sont liés à deux PersonSurveycolonnes qui peuvent (devraient) être dérivées .

À cet égard, vous pouvez déduire la PersonSurvey.IsStarteddonnée par l' interrogation si une donnée Personévénement a fourni un ou plusieurs Responsesà Questionsqui intègrent une exacte Surveyvia la SurveyQuestiontable.

Et vous pouvez également obtenir le PersonSurvey.IsCompletedpoint de données en déterminant si une Personinstance donnée a fourni un Responseà tous ceux Questionsqui co-contiennent une valeur de «VRAI» dans la IsMandatorycolonne d'une SurveyQuestionligne spécifique .

En dérivant ces valeurs, vous évitez certaines anomalies de mise à jour qui se seraient éventuellement produites si vous aviez conservé ces valeurs dans la SurveyQuestioncolonne.

Considération importante

Comme @Dave le fait remarquer à juste titre dans son commentaire, si vous êtes confronté à une exigence future exigeant la gestion de différents types de réponses impliquant la gestion des dates, des valeurs numériques, des choix multiples et d'autres aspects possibles, vous devrez étendre cette disposition de base de données.

MDCCL
la source
1
Wow, cela a parfaitement répondu à la question dans ma tête et m'a ensuite appris plus! Étant donné que les commentaires devraient suggérer des améliorations: il était légèrement déroutant que les clés se terminent par les deux IDet Number, mais sinon, c'est fantastique. Je vous remercie.
Zach Mierzejewski
@Zach Vous êtes les bienvenus, je suis heureux que le message vous ait aidé. Merci pour la rétroaction, certaines améliorations sont décidément nécessaires.
MDCCL
1

C'est une des raisons pour lesquelles je n'aime pas préfixer les colonnes lors de leur migration en tant que clés étrangères. Dans votre premier cas, l'outil de modélisation peut vous obliger à préfixer l'une des survey_idcolonnes du survey_person_question_responsetableau. Vous pourrez peut-être ajuster cela une fois la relation établie.

Si nécessaire, supprimez le champ ID d'enquête redondant lorsque vous créez le modèle physique là où vous n'avez pas besoin de la colonne dupliquée. Comme vous l'avez identifié, vos deux modèles ont des problèmes, mais je pense que le premier modèle est globalement meilleur.

BillThor
la source
Merci pour la perspicacité - je me suis effondré à 1 colonne dans le modèle physique qui applique tout ce que je voulais.
deadcode