Il miglior approccio alla modellazione dei dati per gestire chiavi esterne ridondanti in un database su sondaggi, domande e risposte


13

Sto cercando consigli sul miglior approccio alla modellazione relazionale per archiviare sondaggi, domande e risposte.

Sto cercando quale dei due approcci di seguito sembra migliore o un approccio alternativo a entrambi.

Ho almeno queste entità:

  • domanda
  • sondaggio
  • persona

E almeno queste relazioni:

  • Ogni sondaggio ha 1 o più domande.
  • Ogni domanda può essere utilizzata in 0 o più sondaggi.
  • Ogni persona può prendere 0 o più sondaggi.

Qui è dove mi trovo nei guai: come modellare le risposte alle domande del sondaggio fatte da una persona.

Ecco due approcci che ho preso in considerazione, nessuno dei quali mi sembra molto buono. I diagrammi qui sono notevolmente semplificati per illustrare il problema.

Approccio 1: Approccio 1

Cosa non mi piace di questo approccio:

  • La survey_person_question_responsetabella ha due diverse colonne che fanno riferimento a un sondaggio: survey_question_survey_idesurvey_person_survey_id
    • Sarebbe un errore avere survey_idriferimenti diversi in una riga per queste due colonne. Survey_question deve provenire dallo stesso sondaggio della persona che ha partecipato a survey_person. Non riesco a vedere un buon modo per far valere questo.
  • Sembra che quello che sto facendo qui sia stabilire una relazione tra due relazioni. Mi sembra sbagliato per qualche motivo.

Approccio 2:

Cerca di evitare due FK dall'approccio 1 che dovrebbero fare riferimento allo stesso valore ... inserisci qui la descrizione dell'immagine

Cosa non mi piace di questo approccio:

  • Non è possibile applicare che gli question_ide survey_idFK provengano da una survey_questioncoppia valida
  • Non è possibile applicare che gli survey_ide person_idFK provengano da una survey_personcoppia valida

Qualche consiglio su:

  • Se uno di questi approcci è un approccio tipico
  • Pro e contro di uno di questi approcci rispetto all'altro
  • Un modo migliore per organizzare interamente questi dati

Sarebbe molto apprezzato!

Risposte:


12

Secondo la mia comprensione delle vostre specifiche, il vostro ambiente aziendale implica una relazione ternaria a livello concettuale . A questo proposito, è necessario definire:

  1. il tipo di relazione (o associazione ) tra i tipi di entità Person e Survey ;
  2. il tipo di relazione tra Sondaggio e Domanda ;
  3. il tipo di relazione che stabilisce la connessione tra i due suddetti tipi di relazione e, di conseguenza, tra Persona , Sondaggio e Domanda , ovvero Risposta (un nome più breve che semplifica l'interpretazione, dal mio punto di vista).

Quindi, ritengo che tu sia sulla buona strada con il tuo Approccio 1 , anche se richiede alcuni piccoli (ma importanti) perfezionamenti per renderlo più accurato. Descriverò in dettaglio tali perfezionamenti e altre considerazioni pertinenti nelle sezioni seguenti.

Regole di business

Ampliamo un po 'le regole aziendali applicabili e riformuliamole nel modo seguente:

  • Una persona registra in zero-one-o-many Surveys
  • Un sondaggio ottiene la registrazione di zero-uno-o-molte persone
  • Un sondaggio è integrato da una a molte domande
  • Una domanda integra zero-one-o-many Surveys
  • Una domanda riceve zero-una-o-molte risposte
  • Una risposta è fornita da esattamente una persona nel contesto di esattamente un sondaggio

Diagramma IDEF1X dell'esposizione

Quindi, ho creato l'IDEF1X un diagramma che è presentato in Figura 1 , che sintetizza le regole di business formulate sopra:

Fig.1 Sondaggio semplificato IDEF1X


una definizione di integrazione per la modellazione delle informazioni ( IDEF1X ) è una tecnica di modellazione altamente raccomandabile che è stata stabilita come standard nel dicembre 1993 dal National Institute of Standards and Technology ( NIST )degli Stati Uniti. È solidamente basato sul lavoro teorico creato dall'unico fondatore del modello relazionale , vale a dire il dott. EF Codd e anche sulla visione entità-relazione sviluppata dal dott. PP Chen .


La relazione PersonSurvey

A mio avviso , la relazione PersonSurvey è tenuta a fornire un mezzo di autorizzazione affinché una persona possa prendere parte a un determinato sondaggio . In questo modo, una volta che una determinata persona è stata registrata in un sondaggio specifico , è autorizzata a fornire risposte alle domande che integrano il rispettivo sondaggio .

La relazione SurveyQuestion

Suppongo che la proprietà (o l'attributo) chiamata suvery_question.question_number nel diagramma sia utilizzata per rappresentare l' ordine di presentazione di una determinata istanza della domanda rispetto a un determinato sondaggio . Come puoi vedere, ho indicato una proprietà come SurveyQuestion.PresentationOrder e penso che dovresti impedire che (i) due o più valori Question.QuestionNumber condividano (ii) lo stesso valore PresentationOrder in (iii) la stessa occorrenza di SurveyQuestion .

Per illustrare tale necessità, ho incluso un ALTERNATE KEY composito (AK) nella casella che rappresenta questo tipo di entità, che comprende la combinazione di proprietà ( SurveyNumber, QuestionNumber, PresentationOrder ). Come ben sapete, un AK composito può essere dichiarato in un progetto DDL logico con l'aiuto di un vincolo UNIQUE multi-colonna (come ho esemplificato nella SurveyQuestiontabella che fa parte del layout DDL espositivo esposto alcune sezioni di seguito).

Il tipo di entità Response

Sì, con il tipo di entità Response sto descrivendo una relazione tra altre due relazioni ; esso può sembrare imbarazzante a prima vista, ma non c'è niente di sbagliato in questo approccio, finché (a) rappresenta le caratteristiche del contesto di business di interesse in modo accurato e (b) è rappresentato correttamente in un layout logico di livello.

Sì, hai perfettamente ragione, sarebbe un errore rappresentare quella parte dello scenario a livello logico di astrazione per mezzo di due Response.SurveyNumber(o, diciamo, Response.SurveyId) valori a cui fanno riferimento due colonne diverse nella stessa Responseriga.

Layout logico SQL-DDL derivato

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

Due tasti ESTERI compositi nella Responsetabella

Questo è, probabilmente, il punto più importante da discutere: i riferimenti fatti da una data Responseriga a

  1. SurveyQuestion.SurveyNumber, e
  2. SurveyPerson.SurveyNumber

deve avere valori corrispondenti . Per quanto mi riguarda, l'opzione migliore per applicare questa condizione in modo dichiarativo è l'uso di due CHIAVE STRANIERE composte (FK).

Come mostrato nel progetto DDL, il primo FK sta facendo un riferimento alla PersonSurveytabella PRIMARY KEY (PK), ovvero (PersonId, SurveyNumber), ed è conforme alle colonne Response.PersonIde Response.SurveyNumber.

Il secondo FK punta alla SurveyQuestiontabella PK, ovvero (SurveyNumber, QuestionNumber), ed è, di conseguenza, composto dalle colonne Response.SurveyNumbere Response.QuestionNumber.

In questo modo, la Response.SurveyNumbercolonna è piuttosto strumentale poiché viene utilizzata come parte di un riferimento FK in due diversi vincoli.

Con questo metodo, si garantisce l' integrità referenziale garantita dal sistema di gestione del database

  • (a) Responseal PersonSurvey;
  • (b) Responseal SurveyQuestion; e
  • (c) ciascuna delle tabelle che rappresentano un tipo di entità associativa alle tabelle che rappresentano tipi di entità indipendenti, vale a dire Person, Surveye Question.

Dati derivati ​​per evitare anomalie di aggiornamento

Ho notato nel tuo diagramma due elementi che valuto la pena menzionare. Questi elementi sono correlati a due PersonSurveycolonne che possono (dovrebbero) essere derivate .

A tale proposito, è possibile derivare l'origine PersonSurvey.IsStartedeseguendo una query se una determinata Personoccorrenza ne ha fornito uno o più Responsesper Questionsintegrare un esatto Surveytramite la SurveyQuestiontabella.

E puoi anche ottenere il PersonSurvey.IsCompletedpunto dati determinando se una determinata Personistanza ha fornito Responsea tutto Questionsciò che contiene un valore di "VERO" nella IsMandatorycolonna in una SurveyQuestionriga specifica .

Tramite la derivazione di questi valori, si stanno impedendo alcune anomalie di aggiornamento che si sarebbero eventualmente verificate nel caso in cui si fossero mantenuti tali valori nella SurveyQuestioncolonna.

Considerazione importante

Come giustamente sottolinea @Dave nel suo commento, se si fronteggia un requisito futuro che richiede la gestione di diversi tipi di risposte che implicano la gestione di date, valori numerici, scelta multipla e altri possibili aspetti, sarà necessario estendere questo layout del database.


1
Wow, questo ha risposto perfettamente alla domanda nella mia testa e poi mi ha insegnato di più! Dato che i commenti dovrebbero suggerire miglioramenti: è stato un po 'confuso che le chiavi siano terminate con entrambi IDe Number, ma per il resto è fantastico. Grazie.
Zach Mierzejewski,

@Zach Di niente, sono contento che il post ti abbia aiutato. Grazie per il feedback, alcuni perfezionamenti sono decisamente richiesti.
MDCCL,

1

Questo è uno dei motivi per cui non mi piace aggiungere il prefisso alle colonne durante la migrazione come chiavi esterne. Nel tuo primo caso, lo strumento di modellazione potrebbe costringerti a aggiungere un prefisso a una delle survey_idcolonne nella survey_person_question_responsetabella. Potresti essere in grado di adattarlo dopo aver stabilito la relazione.

Se necessario, rimuovere il campo ID sondaggio ridondante quando si crea il modello fisico in cui non è necessaria la colonna duplicata. Come hai identificato, entrambi i tuoi modelli hanno problemi, ma credo che il primo modello sia complessivamente migliore.


Grazie per l'intuizione - Ho fatto crollare fino a 1 colonna nel modello fisico che rafforza tutto ciò che volevo.
deadcode
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.