วิธีการสร้างแบบจำลองข้อมูลที่ดีที่สุดเพื่อจัดการกับคีย์ต่างประเทศที่ซ้ำซ้อนในฐานข้อมูลเกี่ยวกับแบบสำรวจคำถามและคำตอบ


13

ฉันกำลังมองหาคำแนะนำเกี่ยวกับวิธีการสร้างแบบจำลองเชิงสัมพันธ์ที่ดีที่สุดในการจัดเก็บแบบสอบถามคำถามและคำตอบ

ฉันกำลังมองหาวิธีใดวิธีหนึ่งจากสองวิธีด้านล่างนี้ดูดีที่สุดหรือเป็นทางเลือกอื่นสำหรับทั้งสองวิธี

ฉันมีเอนทิตีเหล่านี้อย่างน้อย:

  • คำถาม
  • สำรวจ
  • คน

และอย่างน้อยความสัมพันธ์เหล่านี้:

  • แบบสำรวจแต่ละแบบมีคำถาม 1 ข้อขึ้นไป
  • คำถามแต่ละข้ออาจใช้ในการสำรวจ 0 ครั้งขึ้นไป
  • แต่ละคนอาจทำการสำรวจ 0 ครั้งขึ้นไป

ที่นี่ฉันเจอปัญหา: วิธีจำลองแบบการตอบสนองต่อคำถามสำรวจโดยบุคคล

ต่อไปนี้เป็นสองวิธีที่ฉันได้พิจารณาซึ่งไม่ได้ดูดีสำหรับฉันเลย ไดอะแกรมที่นี่เรียบง่ายเป็นอย่างมากเพื่อแสดงให้เห็นปัญหา

วิธีที่ 1: วิธีที่ 1

สิ่งที่ฉันไม่ชอบเกี่ยวกับวิธีการนี้:

  • survey_person_question_responseตารางมีสองคอลัมน์ที่แตกต่างกันที่อ้างถึงการสำรวจ: survey_question_survey_idและsurvey_person_survey_id
    • มันจะเป็นข้อผิดพลาดที่มีsurvey_idการอ้างอิงที่แตกต่างกันในหนึ่งแถวสำหรับสองคอลัมน์นี้ Survey_question จะต้องมาจากแบบสำรวจเดียวกับคนที่เข้าร่วมใน survey_person ฉันไม่เห็นวิธีที่ดีในการบังคับใช้
  • ดูเหมือนว่าสิ่งที่ฉันทำที่นี่คือการสร้างความสัมพันธ์ระหว่างสองความสัมพันธ์ นั่นทำให้ฉันรู้สึกผิดด้วยเหตุผลบางอย่าง

วิธีที่ 2:

พยายามหลีกเลี่ยงสอง FKs จากวิธีที่ 1 ที่ควรอ้างอิงถึงค่าเดียวกัน ... ป้อนคำอธิบายรูปภาพที่นี่

สิ่งที่ฉันไม่ชอบเกี่ยวกับวิธีการนี้:

  • ไม่มีการบังคับใช้ว่าquestion_idและsurvey_idFK นั้นมาจากsurvey_questionคู่ที่ถูกต้อง
  • ไม่มีการบังคับใช้ว่าsurvey_idและperson_idFK นั้นมาจากsurvey_personคู่ที่ถูกต้อง

คำแนะนำใด ๆ เกี่ยวกับ:

  • ไม่ว่าหนึ่งในวิธีการเหล่านี้เป็นวิธีการทั่วไปหรือไม่
  • ข้อดีข้อเสียของหนึ่งในวิธีการเหล่านี้มากกว่าที่อื่น
  • วิธีที่ดีกว่าในการจัดเรียงข้อมูลนี้ทั้งหมด

จะได้รับการชื่นชมอย่างมาก!

คำตอบ:


12

ตามความเข้าใจของฉันของข้อกำหนดของสภาพแวดล้อมทางธุรกิจของคุณที่เกี่ยวข้องกับความคิดระดับความสัมพันธ์ ternary ในเรื่องนี้คุณต้องกำหนด:

  1. ความสัมพันธ์ (หรือสมาคม ) ประเภทระหว่างประเภทนิติบุคคลบุคคลและการสำรวจ ;
  2. ประเภทความสัมพันธ์ระหว่างการสำรวจและคำถาม ;
  3. ประเภทความสัมพันธ์ที่สร้างการเชื่อมต่อระหว่างสองประเภทความสัมพันธ์ดังกล่าวและเป็นผลระหว่างบุคคล , การสำรวจและคำถามคือการตอบสนอง (ชื่อที่สั้นลงที่ช่วยลดการตีความจากมุมมองของฉัน)

ดังนั้นฉันคิดว่าคุณอยู่ในแนวทางที่ถูกต้องกับแนวทางที่ 1แม้ว่าจะต้องมีการปรับแต่งเล็กน้อย (แต่สำคัญ) เพื่อให้แม่นยำยิ่งขึ้น ฉันจะดูรายละเอียดการปรับแต่งและข้อควรพิจารณาอื่น ๆ ที่เกี่ยวข้องในส่วนต่อไปนี้

กฎเกณฑ์ทางธุรกิจ

ให้เราขยายกฎเกณฑ์ทางธุรกิจที่เกี่ยวข้องเล็กน้อยและปรับโครงสร้างใหม่ด้วยวิธีต่อไปนี้:

  • คนลงทะเบียนในศูนย์หนึ่งหรือหลายแบบสำรวจ
  • การสำรวจได้รับการลงทะเบียนของบุคคลที่เป็นศูนย์หนึ่งหรือหลายคน
  • การสำรวจนั้นรวมอยู่ในคำถามแบบหนึ่งต่อหลายคำถาม
  • คำถามรวมศูนย์หนึ่งหรือหลายแบบสำรวจ
  • คำถามที่ได้รับเป็นศูนย์หนึ่งหรือหลายคำตอบ
  • การตอบสนองนั้นได้รับการจัดทำโดยบุคคลที่ถูกต้องหนึ่งคนในบริบทของการสำรวจที่แน่นอน

ไดอะแกรม IDEF1X ของที่เก็บข้อมูล

จากนั้นเราได้สร้าง IDEF1X แผนภาพที่นำเสนอในรูปที่ 1ซึ่งสังเคราะห์กฎเกณฑ์ทางธุรกิจสูตรข้างต้น:

รูปที่ 1 การสำรวจอย่างง่าย IDEF1X


นิยามบูรณาการสำหรับแบบจำลองข้อมูล ( IDEF1X ) เป็นเทคนิคการสร้างแบบจำลองฝากฝังสูงที่ได้รับการยอมรับว่าเป็นมาตรฐานในเดือนธันวาคมปี 1993 โดยสหรัฐอเมริกาชาติสถาบันมาตรฐานและเทคโนโลยี ( NIST ) มันขึ้นอยู่กับการทำงานอย่างสมบูรณ์ทฤษฎีประพันธ์โดยผู้ก่อตั้ง แต่เพียงผู้เดียวของแบบเชิงสัมพันธ์คือดร. EF Coddและยังอยู่ในมุมมองนิติบุคคลความสัมพันธ์ที่พัฒนาโดยดร. พีพีเฉิน


PersonSurveyความสัมพันธ์

ที่ผมเห็นมันPersonSurveyความสัมพันธ์จะต้องให้ความหมายของการอนุมัติเพื่อให้คนสามารถมีส่วนร่วมในการที่ได้รับการสำรวจ ด้วยวิธีนี้เมื่อบางคนได้รับการจดทะเบียนในเฉพาะการสำรวจเขาหรือเธอเป็นผู้มีอำนาจที่จะให้คำตอบกับคำถามที่ว่าบูรณาการที่เกี่ยวข้องสำรวจ

แบบสำรวจความสัมพันธ์แบบสอบถาม

ฉันคิดว่าสถานที่ให้บริการ (หรือแอตทริบิวต์) เรียกว่าsuvery_question.question_numberในแผนภาพของคุณจะใช้เพื่อเป็นตัวแทนของการสั่งซื้อของการนำเสนอที่ได้รับคำถามเช่นด้วยความเคารพโดยเฉพาะอย่างยิ่งการสำรวจ อย่างที่คุณเห็นฉันได้แสดงคุณสมบัติเช่นSurveyQuestion.PresentationOrderและฉันคิดว่าคุณควรป้องกัน (i) คำถามสองข้อขึ้นไปคำถามจำนวนคำถามค่าส่วนแบ่ง (ii) ค่าPresentationOrderเดียวกันใน (iii) เหตุการณ์SurveyQuestionเดียวกัน

ในการวาดภาพที่ต้องการฉันได้รวมคีย์ ALTERNATE (AK) ประกอบในกล่องที่แสดงประเภทเอนทิตีนี้ซึ่งประกอบด้วยการรวมกันของคุณสมบัติ ( SurveyNumber, QuestionNumber, PresentationOrder ) ในขณะที่คุณทราบดีคอมโพสิต AK สามารถประกาศในการออกแบบ DDL ตรรกะด้วยความช่วยเหลือของข้อ จำกัด UNIQUE หลายคอลัมน์ (ตามที่ฉันเป็นแบบอย่างในSurveyQuestionตารางที่เป็นส่วนหนึ่งของเค้าโครง DDL expository expounded บางส่วนด้านล่าง)

ประเภทการตอบสนองของนิติบุคคล

ใช่ด้วยประเภทการตอบสนองฉันกำลังแสดงความสัมพันธ์ระหว่างความสัมพันธ์อื่นที่สอง ; มันอาจดูอึดอัดใจในครั้งแรก แต่ไม่มีอะไรผิดปกติกับวิธีการนี้ตราบใดที่มัน (a) แสดงถึงคุณลักษณะของบริบททางธุรกิจที่น่าสนใจอย่างถูกต้องและ (b) แสดงอย่างถูกต้องในรูปแบบตรรกะระดับ

ใช่คุณถูกต้องทั้งหมดมันจะเป็นข้อผิดพลาดในการพรรณนาว่าส่วนหนึ่งของสถานการณ์ในระดับตรรกะของนามธรรมโดยใช้ค่าสอง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ตาราง

นี่อาจเป็นจุดที่สำคัญที่สุดในการพูดคุย: การอ้างอิงที่ทำจากResponseแถวที่ระบุไปยัง

  1. SurveyQuestion.SurveyNumberและ
  2. SurveyPerson.SurveyNumber

ต้องมีค่าที่ตรงกัน เท่าที่ฉันมีความกังวลตัวเลือกที่ดีที่สุดในการบังคับใช้เงื่อนไขนี้ในทางที่เปิดเผยคือการใช้คีย์ผสมสองตัวต่างประเทศ (FK)

ตามที่ปรากฏในการออกแบบ DDL ที่แรก FK คือการทำให้การอ้างอิงไปยังPersonSurveyตารางคีย์หลัก (PK) คือ(PersonId, SurveyNumber)และสอดคล้องตามคอลัมน์และResponse.PersonIdResponse.SurveyNumber

ที่สอง FK จะชี้ไปที่SurveyQuestionPK ตารางเช่น(SurveyNumber, QuestionNumber)และตามขึ้นของคอลัมน์และResponse.SurveyNumberResponse.QuestionNumber

ด้วยวิธีนี้Response.SurveyNumberคอลัมน์ค่อนข้างมีประโยชน์เนื่องจากมันถูกใช้เป็นส่วนหนึ่งของการอ้างอิง FK ในข้อ จำกัด ที่แตกต่างกันสองข้อ

ด้วยวิธีนี้อย่างใดอย่างหนึ่งเพื่อให้แน่ใจว่าการจัดการฐานข้อมูลระบบการรับประกันการอ้างอิงจาก

  • (ก) ResponseไปPersonSurvey;
  • (ข) ResponseไปSurveyQuestion; และ
  • (ค) แต่ละตารางที่เป็นตัวแทนของประเภทกิจการที่เชื่อมโยงไปยังตารางที่ยืนอยู่ประเภทองค์กรอิสระคือPerson, และSurveyQuestion

ข้อมูลที่ได้มาเพื่อหลีกเลี่ยงการปรับปรุงความผิดปกติ

ฉันได้สังเกตุในแผนภาพของคุณองค์ประกอบสองอย่างที่ฉันเห็นคุณค่าน่าพูดถึง องค์ประกอบเหล่านี้เกี่ยวข้องกับสองPersonSurveyคอลัมน์ที่สามารถ (ควร) จะได้มา

ในเรื่องนั้นคุณสามารถได้รับPersonSurvey.IsStartedข้อมูลโดยการสอบถามว่าPersonเหตุการณ์ที่เกิดขึ้นได้ให้หนึ่งหรือมากกว่านั้นResponsesเพื่อQuestionsบูรณาการที่แน่นอนSurveyผ่านทางSurveyQuestionตาราง

และคุณยังสามารถหาPersonSurvey.IsCompletedจุดข้อมูลได้ด้วยการพิจารณาว่าPersonอินสแตนซ์ที่กำหนดได้มอบให้ResponseกับทุกตัวQuestionsที่เก็บค่า 'TRUE' ในIsMandatoryคอลัมน์ในSurveyQuestionแถวที่ระบุ

จากการได้มาของค่าเหล่านี้คุณกำลังป้องกันความผิดปกติของการอัปเดตบางอย่างที่อาจเกิดขึ้นในที่สุดในกรณีที่คุณเก็บค่าดังกล่าวไว้ในSurveyQuestionคอลัมน์

การพิจารณาที่สำคัญ

ตามที่@Daveชี้ให้เห็นอย่างถูกต้องในความคิดเห็นของเขาหากคุณเผชิญกับความต้องการในอนาคตที่ต้องการการจัดการการตอบสนองที่หลากหลายซึ่งบ่งบอกถึงการจัดการวันที่ค่าตัวเลขตัวเลือกที่หลากหลายและด้านอื่น ๆ ที่เป็นไปได้


1
ว้าวสิ่งนี้ตอบคำถามได้อย่างสมบูรณ์แบบในหัวของฉันแล้วสอนฉันให้มากขึ้น! เนื่องจากความคิดเห็นควรแนะนำการปรับปรุง: มันสับสนเล็กน้อยว่าคีย์ที่ลงท้ายด้วยทั้งสองIDและNumberอย่างอื่นนี่เป็นสิ่งที่มหัศจรรย์ ขอขอบคุณ.
Zach Mierzejewski

@Zach คุณยินดีมากที่สุดฉันดีใจที่โพสต์ช่วยคุณ ขอขอบคุณสำหรับข้อเสนอแนะการปรับแต่งบางอย่างจะถูกเรียกโดยเด็ดขาด
MDCCL

1

นี่คือเหตุผลหนึ่งว่าทำไมฉันไม่ชอบคำนำหน้าคอลัมน์เมื่อย้ายพวกเขาเป็นคีย์ต่างประเทศ ในกรณีแรกของคุณเครื่องมือสร้างแบบจำลองอาจบังคับให้คุณนำหน้าหนึ่งในsurvey_idคอลัมน์ในsurvey_person_question_responseตาราง คุณอาจปรับเปลี่ยนได้หลังจากสร้างความสัมพันธ์แล้ว

หากจำเป็นให้ลบฟิลด์รหัสแบบสำรวจซ้ำซ้อนเมื่อคุณสร้างแบบจำลองทางกายภาพที่คุณไม่ต้องการคอลัมน์ที่ซ้ำกัน ตามที่คุณระบุทั้งสองแบบของคุณมีปัญหา แต่ฉันเชื่อว่ารุ่นแรกนั้นโดยรวมดีกว่า


ขอบคุณสำหรับข้อมูลเชิงลึก - ฉันยุบลงไปที่ 1 คอลัมน์ในแบบจำลองทางกายภาพซึ่งบังคับใช้ทุกอย่างที่ฉันต้องการ
deadcode
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.