調査、質問、回答に関するデータベース内の冗長な外部キーを処理するための最良のデータモデリングアプローチ


13

アンケート、質問、回答を保存するための最適なリレーショナルモデリングアプローチに関するアドバイスを探しています。

以下の2つのアプローチのどちらが最適か、またはどちらかに対する代替アプローチを探しています。

私は少なくともこれらのエンティティを持っています:

  • 質問
  • 調査

そして、少なくともこれらの関係:

  • 各調査には1つ以上の質問があります。
  • 各質問は0回以上のアンケートで使用できます。
  • 一人一人が0以上の調査を行うことがあります。

ここで問題が発生します。人が行った調査の質問に対する応答をモデル化する方法。

ここに私が検討した2つのアプローチがありますが、どちらも私には非常に良いとは思えません。この図は、問題を説明するために大幅に簡略化されています。

アプローチ1: アプローチ1

このアプローチについて私が好きではないこと:

  • survey_person_question_responseテーブルには、調査を参照する2つの異なる列がありますsurvey_question_survey_idし、survey_person_survey_id
    • survey_idこれらの2つの列の1つの行で異なるが参照されていると、エラーになります。survey_questionは、survey_personを担当した人と同じ調査のものである必要があります。これを強制する良い方法がわかりません。
  • ここで私がしていることは、2つの関係の関係を作っているようです。なんらかの理由でそれは私には間違っていると感じます。

アプローチ2:

同じ値を参照する必要があるアプローチ1からの2つのFKを避けてください... ここに画像の説明を入力してください

このアプローチについて私が好きではないこと:

  • question_idおよびsurvey_idFKが有効なsurvey_questionペアからのものであるという強制はありません。
  • survey_idおよびperson_idFKが有効なsurvey_personペアからのものであるという強制はありません。

に関するアドバイス:

  • これらのアプローチの1つが典型的なアプローチかどうか
  • これらのアプローチのいずれかの長所と短所
  • このデータを完全に整理するためのより良い方法

いただければ幸いです!

回答:


12

あなたの仕様を理解しているように、ビジネス環境には概念レベルの三項関係が含まれます。これに関して、次のことを定義する必要があります。

  1. エンティティタイプPersonSurvey間の関係(または関連)タイプ。
  2. 調査質問の関係タイプ。
  3. 前述の2つの関係タイプ間の関係を確立する関係タイプ、および結果として、PersonSurvey、およびQuestion間の関係、つまり、Response(私の観点から、解釈を簡略化する短い名前)。

したがって、アプローチ1は正しい方向に進んでいると思いますが、より正確にするためにはいくつかの(しかし重要な)微調整が必​​要です。次のセクションでは、そのような改良点とその他の関連する考慮事項について詳しく説明します。

ビジネスルール

適用可能なビジネスルールを少し拡張して、次のように再定式化しましょう。

  • A 人物ゼロ・ワン・オア・多くのレジスタ調査
  • A 調査は、ゼロ・ワン・オア・多くの登録取得者を
  • A 調査は、 1対多で統合されている質問
  • A 質問は、ゼロ・ワン・オア・多くの統合調査を
  • A 質問は、ゼロ・ワン・オア・多くの受信応答を
  • A 応答は、正確に-1によって提供されるに正確-1のコンテキストで調査

解説IDEF1X図

次に、図1に示すIDEF1X ダイアグラムを作成しまし。これは、上記で定式化されたビジネスルールを統合したものです。

図1簡易調査IDEF1X


インフォメーションモデリングのための統合の定義 IDEF1Xは)として設立された非常にお勧めのモデル化技術である標準米国国立標準技術研究所(で1993年12月に NIST)。これは、リレーショナルモデルの唯一の創設者である EF Codd博士によって作成された理論的研究、および PP Chen博士によって開発されたエンティティ関係ビューにしっかりと基づいています。


PersonSurvey関係

私が見ているように、PersonSurvey関係は、Personが特定のSurveyに参加できるように承認の手段を提供する必要があります。このように、特定の調査に特定の人物が登録されると、その人物は、それぞれの調査を統合する質問に回答する権限を与えられます。

SurveyQuestionの関係

ダイアグラムでsuvery_question.question_numberと呼ばれるプロパティ(または属性)が、特定のSurveyに関する特定のQuestionインスタンスの表示順序を表すために使用されていると思います。ご覧のとおり、このようなプロパティをSurveyQuestion.PresentationOrderと示しましたが、(i)2つ以上のQuestion.QuestionNumber値が(ii)同じPresentationOrder値を(iii)同じSurveyQuestionで共有しないようにする必要があると思います。

その必要性を表現するために、このエンティティタイプを表すボックスに複合の代替キー(AK)を含めました。これは、プロパティの組み合わせ(SurveyNumber、QuestionNumber、PresentationOrder)で構成されています。ご存じのとおり、複合AKは、複数列のUNIQUE制約を使用して論理DDL設計で宣言できます(SurveyQuestion説明用のDDLレイアウトの一部である表で例示したように、以下のいくつかのセクションで説明しています)。

レスポンスエンティティタイプ

はい、Responseエンティティタイプでは、他の2つの関係間の関係を示しています。それが可能であれば()ビジネス正確に関心のコンテキストと、(b)の機能は論理レベルのレイアウトで適切に表現さを表すように、一見厄介なようですが、このアプローチには何も間違っているがあります。

はい、あなたは完全に正しいです。同じ行の2つの異なる列から参照される2 つのResponse.SurveyNumber(または、たとえばResponse.SurveyId)値を使用して、シナリオのその部分を抽象化の論理レベルで表現すると、エラーになりますResponse

派生した論理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)
);

Responseテーブル内の2つの複合外部キー

これはおそらく、議論する最も重要なポイントです。特定のResponse行から

  1. SurveyQuestion.SurveyNumber、および
  2. SurveyPerson.SurveyNumber

一致する値が必要です。私に関する限り、宣言的な方法でこの条件を強制する最良のオプションは、2つの複合外部キー(FK)を使用することです。

DDL設計に示されるように、最初のFKを参照製造されPersonSurvey、すなわち、テーブルPRIMARY KEY(PK)を(PersonId, SurveyNumber)、列によって適合されるResponse.PersonIdResponse.SurveyNumber

2番目のFKはSurveyQuestionテーブルPK、つまりを指しており(SurveyNumber, QuestionNumber)、したがって列Response.SurveyNumberとで構成されていますResponse.QuestionNumber

このように、2つの異なる制約Response.SurveyNumberでFK参照の一部として使用されるため、列は非常に役立ちます。

この方法では、データベース管理システムが保証する参照整合性

  • (a)ResponsePersonSurvey;
  • (b)ResponseSurveyQuestion; そして
  • (c)独立したエンティティタイプを表すテーブルへの関連エンティティタイプを表す各テーブル、つまりPersonSurveyおよびQuestion

更新の異常を回避するための派生データ

あなたの図で、私が言及する価値がある2つの要素に気づきました。これらの要素はPersonSurvey派生できる(する必要がある)2つの列に関連しています。

その点でPersonSurvey.IsStarted、特定のPersonオカレンスがテーブルを介して完全に統合する1つ以上Responsesを提供しているかどうかを照会することにより、データを導出できます。QuestionsSurveySurveyQuestion

また、特定の行の列に「TRUE」の値を含むすべてのインスタンスにPersonSurvey.IsCompleted特定のPersonインスタンスがを提供したかどうかを判断することによって、データポイントを取得することもできます。ResponseQuestionsIsMandatorySurveyQuestion

これらの値の導出により、そのような値をSurveyQuestion列に保持していた場合に最終的に発生する可能性がある更新の異常を防止しています。

重要な考慮事項

以下のよう@Daveは当然彼のコメントで指摘あなたが管理し、日付、数値、複数の選択肢、および他の可能な側面を意味するものでは応答の異なる種類の管理を要求し、将来の要件に直面した場合、あなたはこのデータベースのレイアウトを拡張する必要があります。


1
うわー、これは私の頭の中の質問に完全に答えて、それから私にもっと教えました!コメントは改善を示唆しているので:キーがとの両方IDで終わっていると少し混乱しましたNumberが、それ以外の場合はこれは素晴らしいです。ありがとうございました。
Zach Mierzejewski

@Zachどういたしまして。投稿が役に立ちました。フィードバックのおかげで、いくつかの改良が明らかに求められています。
MDCCL 2018年

1

これが、列を外部キーとして移行するときに列にプレフィックスを付けたくない理由の1つです。最初のケースでは、モデリングツールsurvey_idにより、survey_person_question_responseテーブルの列の1つにプレフィックスを付けるように強制される場合があります。関係が作成された後、これを調整できる場合があります。

必要に応じて、重複した列が不要な物理モデルを構築するときに、冗長な調査IDフィールドを削除します。ご指摘のとおり、どちらのモデルにも問題がありますが、最初のモデルの方が全体的に優れていると思います。


洞察をありがとう-私は私が望んだすべてを実施する物理モデルの1列に縮小しました。
デッドコード2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.