ความแตกต่างระหว่างความสัมพันธ์แบบหนึ่งต่อกลุ่มและแบบกลุ่มต่อหนึ่ง


117

อะไรคือความแตกต่างที่แท้จริงระหว่างความสัมพันธ์แบบหนึ่งต่อกลุ่มและหลายต่อหนึ่ง มันกลับกันเท่านั้นชนิดของ?

ฉันไม่พบบทช่วยสอนที่ 'ดีและเข้าใจง่าย' เกี่ยวกับหัวข้อนี้นอกเหนือจากหัวข้อนี้: SQL for Beginners: ตอนที่ 3 - ความสัมพันธ์ของฐานข้อมูล


1
นี่คือคำอธิบายที่สมบูรณ์แบบ: en.wikipedia.org/wiki/Many-to-many_(data_model)
RobertPitt

@RobertPitt บทความแบบกลุ่มต่อกลุ่มเกี่ยวข้องกับคำถามอย่างไร คุณน่าจะหมายถึงen.wikipedia.org/wiki/One-to-many_(data_model)
TMG

คำตอบ:


111

ใช่มันในทางกลับกัน ขึ้นอยู่กับว่าเอนทิตีนั้นมีความสัมพันธ์ด้านใด

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

ข้อมูลเพิ่มเติมเกี่ยวกับประเภทความสัมพันธ์:

ความสัมพันธ์ของฐานข้อมูล - เอกสาร IBM DB2


2
กลัวไม่ได้จัดฉาก! ( ไม่แน่ใจ ) ฉันคิดว่าคำสั่งนี้แสดงถึงการพึ่งพา! ไม่ใช่หรอ ?? เช่นผู้ใช้ต่อบทบาทอาจเป็น 1 ต่อหลายคน แต่ไม่มากต่อหนึ่งเพราะไม่สามารถรับการอ้างอิงของผู้ใช้ที่ใช้บทบาทได้! มันสมเหตุสมผลไหม
Amanuel Nega


29

จากหน้านี้เกี่ยวกับคำศัพท์ฐานข้อมูล

ความสัมพันธ์ระหว่างตารางส่วนใหญ่เป็นแบบหนึ่งต่อกลุ่ม

ตัวอย่าง:

  • พื้นที่หนึ่งสามารถเป็นที่อยู่อาศัยของผู้อ่านจำนวนมาก
  • ผู้อ่านหนึ่งคนสามารถสมัครรับข้อมูลได้หลายรายการ
  • หนังสือพิมพ์หนึ่งฉบับสามารถสมัครสมาชิกได้หลายฉบับ

ความสัมพันธ์แบบกลุ่มต่อหนึ่งเหมือนกับกลุ่มหนึ่งต่อกลุ่ม แต่มาจากมุมมองที่แตกต่างกัน

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

20

อะไรคือความแตกต่างที่แท้จริงระหว่างความสัมพันธ์แบบหนึ่งต่อกลุ่มและหลายต่อหนึ่ง

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

ในหนึ่งต่อหลายความสัมพันธ์ของตารางในท้องถิ่นมีหนึ่งแถวนั้นอาจจะเกี่ยวข้องกับหลายแถวในตารางอื่น ในตัวอย่างจากSQL สำหรับผู้เริ่มต้นหนึ่งCustomerอาจจะเกี่ยวข้องกับหลายOrders

ในตรงข้ามหลายต่อหนึ่งความสัมพันธ์ของตารางในท้องถิ่นอาจมีหลายแถวที่เกี่ยวข้องกับหนึ่งแถวในตารางอื่น ในตัวอย่างของเราหลายOrders Customerอาจจะเกี่ยวข้องกับหนึ่ง ความแตกต่างทางความคิดนี้มีความสำคัญต่อการแสดงจิต

นอกจากนี้สคีมาที่รองรับความสัมพันธ์อาจแสดงแตกต่างกันในตารางCustomerและ Orderตัวอย่างเช่นหากลูกค้ามีคอลัมน์idและname:

id,name
1,Bill Smith
2,Jim Kenshaw

จากนั้นสำหรับการOrderเชื่อมโยงกับ a Customerการใช้งาน SQL จำนวนมากจะเพิ่มOrderคอลัมน์ที่เก็บข้อมูลidที่เกี่ยวข้องลงCustomerในตาราง (ในสคีมานี้customer_id:

id,date,amount,customer_id
10,20160620,12.34,1
11,20160620,7.58,1
12,20160621,158.01,2

ในแถวข้อมูลด้านบนหากเราดูcustomer_idคอลัมน์ id เราจะเห็นว่าBill Smith(customer-id # 1) มีคำสั่งซื้อ 2 รายการที่เกี่ยวข้องกับเขาคำสั่งซื้อหนึ่งราคา 12.34 ดอลลาร์และอีกรายการหนึ่งในราคา 7.58 ดอลลาร์ Jim Kenshaw(customer-id # 2) มีเพียง 1 คำสั่งซื้อในราคา $ 158.01

สิ่งสำคัญที่ต้องตระหนักก็คือโดยทั่วไปแล้วความสัมพันธ์แบบหนึ่งต่อกลุ่มจะไม่เพิ่มคอลัมน์ใด ๆ ลงในตารางที่เป็น "หนึ่ง" ไม่มีคอลัมน์พิเศษที่อธิบายความสัมพันธ์กับCustomer Orderในความเป็นจริงแล้วCustomerอาจมีความสัมพันธ์แบบหนึ่งต่อกลุ่มShippingAddressและSalesCallตารางและยังไม่มีคอลัมน์เพิ่มเติมในCustomerตาราง

อย่างไรก็ตามสำหรับความสัมพันธ์แบบกลุ่มต่อกลุ่มที่จะอธิบายมักจะมีการidเพิ่มคอลัมน์ลงในตาราง "many" ซึ่งเป็นคีย์ต่างประเทศในตาราง "หนึ่ง" - ในกรณีนี้customer_idจะมีการเพิ่มคอลัมน์ลงในOrder. สำหรับคำสั่งซื้อที่เกี่ยวข้อง # 10 ในราคา $ 12.34 ถึงBill Smithเรากำหนดcustomer_idคอลัมน์ให้กับBill Smithid 1

อย่างไรก็ตามเป็นไปได้เช่นกันที่จะมีตารางอื่นที่อธิบายถึงความสัมพันธ์CustomerและOrderความสัมพันธ์ดังนั้นจึงไม่จำเป็นต้องเพิ่มฟิลด์เพิ่มเติมในOrderตาราง แทนที่จะเพิ่มcustomer_idเขตข้อมูลลงในOrderตารางอาจมีCustomer_Orderตารางที่มีคีย์สำหรับทั้งCustomerและOrder.

customer_id,order_id
1,10
1,11
2,12

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

หวังว่านี่จะช่วยได้


3
กรณีทั่วไปเรียกว่าการพึ่งพาการรวม ข้อ จำกัด ของคีย์ต่างประเทศเป็นประเภทของการพึ่งพาการรวมที่พบบ่อยที่สุด แต่การอ้างอิงการรวมทั้งหมดไม่เกี่ยวข้องกับคีย์ต่างประเทศ แอตทริบิวต์ทั่วไปหรือแอตทริบิวต์ ("การอ้างอิง") ​​มีอยู่ในทั้งสองตารางเสมอ ในด้าน "หนึ่ง" แอตทริบิวต์เหล่านี้เรียกว่าคีย์ตัวเลือก ในด้าน "หลาย" อาจเป็นคีย์ต่างประเทศ คำว่า "หนึ่งต่อหลาย" หรือ "หลายต่อหนึ่ง" สามารถนำไปใช้กับการพึ่งพาการรวมที่เกี่ยวข้องกับคีย์ผู้สมัครอย่างน้อยหนึ่งรายการโดยไม่จำเป็นต้องระบุว่าด้านใดอาจเป็นทางเลือกก็ได้
nvogel

@sqlvogel ที่น่าสนใจ ใน Java javax.persistence.OneToManyแตกต่างจากManyToOne. คุณบอกว่าตรงกันหรือแค่ขึ้นอยู่กับการนำไปใช้งาน? คำตอบของฉันไม่ถูกต้องหรือไม่?
Grey

2
คำถามเกี่ยวกับฐานข้อมูลเชิงสัมพันธ์และ SQL ไม่ใช่ Java บางทีคุณอาจจะพูดถูกเกี่ยวกับ Java
nvogel

ฉันใช้มันเป็นตัวอย่าง @sqlvogel คุณกำลังบอกว่า "หนึ่งต่อหลาย" และ "หลายต่อหนึ่ง" ตรงกันหรือไม่
Grey

2
ฉันกำลังบอกว่านั่นเป็นสองวิธีในการอธิบายความสัมพันธ์ที่เหมือนกัน แต่มาจากมุมมองที่ต่างกัน ในทำนองเดียวกันว่า "A เป็นส่วนย่อยของ B" หมายถึงเช่นเดียวกับ "B คือส่วนเหนือของ A"
nvogel

4

ไม่มีความแตกต่างกัน มันเป็นเรื่องของภาษาและความชอบว่าคุณจะพูดถึงความสัมพันธ์แบบไหน


1
แน่นอนว่ามีความแตกต่างทั้งในเชิงแนวคิดและสคีมาที่สร้างขึ้น ดูคำตอบของฉัน: stackoverflow.com/a/37954280/179850
สีเทา

4
@Gray ไม่มีไม่มี คำตอบของคุณไม่เพียง แต่ไม่ถูกต้อง แต่ยังสร้างความสับสนให้กับผู้เริ่มต้น (คนที่ถามคำถามนี้)
PerformanceDBA

4

คำตอบสำหรับคำถามแรกของคุณคือทั้งคู่คล้ายกัน

คำตอบสำหรับคำถามที่สองของคุณคือ: แบบตัวต่อตัว -> ผู้ชาย (โต๊ะผู้ชาย) อาจมีภรรยามากกว่าหนึ่งคน (โต๊ะผู้หญิง) แบบหลายคนต่อหนึ่ง -> ผู้หญิงมากกว่าหนึ่งคนได้แต่งงานกับผู้ชายหนึ่งคน

ตอนนี้ถ้าคุณต้องการเชื่อมโยงความสัมพันธ์นี้กับสองตาราง MAN และ WOMEN หนึ่งแถวของตาราง MAN อาจมีความสัมพันธ์กับแถวต่างๆในตาราง WOMEN หวังว่ามันจะชัดเจน


3

ตัวอย่าง

สองตารางที่มีความสัมพันธ์เดียว

SQL

ใน SQL มีความสัมพันธ์เพียงชนิดเดียวเรียกว่าการอ้างอิง (ส่วนหน้าของคุณอาจทำสิ่งที่เป็นประโยชน์หรือสับสน [เช่นในคำตอบบางส่วน] แต่นั่นเป็นคนละเรื่อง)

  • ต่างประเทศที่สำคัญในตารางหนึ่ง (คนreferenc ไอเอ็นจีตาราง)
    อ้างอิงคีย์หลักในตารางอื่น (คนreferenc เอ็ดตาราง)
  • ในแง่ SQL แถบอ้างอิง Foo
    ไม่ใช่วิธีอื่น

    CREATE TABLE Foo (
        Foo   CHAR(10)  NOT NULL, -- primary key
        Name  CHAR(30)  NOT NULL
        CONSTRAINT PK             -- constraint name
            PRIMARY KEY (Foo)     -- pk
        )  
    CREATE TABLE Bar (
        Bar   CHAR(10)  NOT NULL, -- primary key
        Foo   CHAR(10)  NOT NULL, -- foreign key to Foo
        Name  CHAR(30)  NOT NULL
        CONSTRAINT PK                -- constraint name
            PRIMARY KEY (Bar),       -- pk
        CONSTRAINT Foo_HasMany_Bars  -- constraint name
            FOREIGN KEY   (Foo)      -- fk in (this) referencing table
            REFERENCES Foo(Foo)      -- pk in referenced table
        )
  • เนื่องจากFoo.Fooเป็นคีย์หลักจึงไม่ซ้ำกันมีเพียงแถวเดียวสำหรับค่าที่ระบุFoo

  • เนื่องจากBar.Fooเป็นการอ้างอิงคีย์ต่างประเทศและไม่มีดัชนีที่ไม่ซ้ำกันจึงอาจมีหลายแถวสำหรับค่าที่กำหนดของFoo
  • ดังนั้นความสัมพันธ์Foo::Barจึงเป็นแบบหนึ่งต่อกลุ่ม
  • ตอนนี้คุณสามารถรับรู้ (มอง) ความสัมพันธ์ในทางกลับกันBar::Fooคือแบบหลายต่อหนึ่ง
    • แต่อย่าปล่อยให้สิ่งนั้นทำให้คุณสับสน: สำหรับBarแถวใดแถวหนึ่งมีเพียงFooแถวเดียวที่อ้างอิง
  • ใน SQL นั่นคือทั้งหมดที่เรามี นั่นคือสิ่งที่จำเป็นทั้งหมด

อะไรคือความแตกต่างที่แท้จริงระหว่างความสัมพันธ์แบบหนึ่งต่อกลุ่มและหลายต่อหนึ่ง

มีความสัมพันธ์เดียวจึงไม่มีความแตกต่างกัน การรับรู้ (จาก "จุดสิ้นสุด" หนึ่งหรือ "จุดสิ้นสุด" อื่น ๆ ) หรือการอ่านย้อนหลังจะไม่เปลี่ยนความสัมพันธ์

cardinality

คาร์ดินาลิตี้ถูกประกาศก่อนในโมเดลข้อมูลซึ่งหมายถึงตรรกะและกายภาพ (เจตนา) จากนั้นในการนำไปใช้งาน (เจตนาที่รับรู้)

cardinality

หนึ่งถึงศูนย์ต่อกลุ่ม
ใน SQL ที่ (ด้านบน) เป็นสิ่งที่จำเป็นทั้งหมด

หนึ่งต่อหนึ่งต่อหลาย
คุณต้องการไฟล์ธุรกรรมเพื่อบังคับใช้รายการในตารางอ้างอิง

หนึ่งถึงศูนย์ต่อหนึ่งที่
คุณต้องการในBar:

CONSTRAINT AK    -- constraint name
    UNIQUE (Foo) -- unique column, which makes it an Alternate Key

หนึ่งต่อหนึ่ง
คุณต้องมีทำธุรกรรมเพื่อบังคับใช้ในตารางอ้างอิง

หลายต่อหลายคน
ไม่มีสิ่งเหล่านี้ในระดับกายภาพ (จำได้ว่ามีความสัมพันธ์เพียงประเภทเดียวใน SQL)

ในระดับลอจิกตอนต้นระหว่างแบบฝึกหัดการสร้างแบบจำลองจะสะดวกในการวาดความสัมพันธ์ดังกล่าว ก่อนที่โมเดลจะเข้าใกล้การนำไปใช้จริงควรยกระดับให้ใช้เฉพาะสิ่งที่มีอยู่ได้ดีกว่า ความสัมพันธ์ดังกล่าวได้รับการแก้ไขโดยการใช้ Associative Table

หลายต่อหลายคนได้รับการแก้ไข


1
@Martijn ปีเตอร์ส. ฉันสามารถแก้ไขได้เพื่อให้สอดคล้องกับจรรยาบรรณ แต่คุณได้ลบ (a) คำอธิบายและ (b) หลักฐานข้อเท็จจริงในความเป็นจริง ฉันจะทำอย่างไรกับสิ่งเหล่านั้น
PerformanceDBA

3
ค้นหาวิธีที่แตกต่างออกไปในการแสดงออกถึงสิ่งเหล่านั้นโดยไม่ต้องใช้การพูดจาโผงผางการเรียกชื่อและการแสดงความคิดเห็นเกี่ยวกับสติปัญญาหรือการปฏิบัติอย่างมืออาชีพของใครก็ตาม มุ่งเน้นไปที่เทคโนโลยีไม่ใช่คนที่อาจผิดหรือไม่ผิด
Martijn Pieters

2

One-to-Many และ Many-to-One มีความคล้ายคลึงกันใน Multiplicity แต่ไม่ใช่ Aspect (เช่น Directionality)

การแม็ปความสัมพันธ์ระหว่างคลาสเอนทิตีและความสัมพันธ์ระหว่างตาราง ความสัมพันธ์มีสองประเภท:

  1. หลายหลาก (คำ ER: cardinality)
    • ความสัมพันธ์แบบหนึ่งต่อหนึ่ง : ตัวอย่างสามีและภรรยา
    • ความสัมพันธ์แบบหนึ่งต่อกลุ่ม : ตัวอย่างแม่และเด็ก
    • ความสัมพันธ์แบบกลุ่มต่อกลุ่ม : ตัวอย่างนักเรียนและหัวเรื่อง
  2. ทิศทาง : ไม่มีผลต่อการทำแผนที่ แต่สร้างความแตกต่างในการเข้าถึงข้อมูล
    • ความสัมพันธ์แบบทิศทางเดียว : ฟิลด์ความสัมพันธ์หรือคุณสมบัติที่อ้างถึงเอนทิตีอื่น
    • ความสัมพันธ์แบบสองทิศทาง : แต่ละเอนทิตีมีฟิลด์ความสัมพันธ์หรือคุณสมบัติที่อ้างถึงเอนทิตีอื่น

ไม่มี "ทิศทาง" ในฐานข้อมูลเชิงสัมพันธ์ แต่ละความสัมพันธ์มี "จุดจบ" สองรายการ ได้แก่ Reference (ตารางที่กำลังอ้างอิง) และการอ้างอิง (ตารางที่ทำการอ้างอิง) SQL / DML ช่วยให้สามารถอ้างอิงตารางใดก็ได้ในแบบที่คุณต้องการ ... ด้านหนึ่ง ... อีกด้านหนึ่ง ... ทั้งสองด้าน ... ไม่มีด้าน
PerformanceDBA

0

ไม่มีความแตกต่างในทางปฏิบัติ เพียงแค่ใช้ความสัมพันธ์ที่เหมาะสมกับวิธีที่คุณเห็นปัญหาของคุณตามที่ Devendra แสดงไว้


แน่นอนว่ามีความแตกต่างทั้งในเชิงแนวคิดและสคีมาที่สร้างขึ้น ดูคำตอบของฉัน: stackoverflow.com/a/37954280/179850
สีเทา

3
@Gray ไม่มีไม่มี คำตอบของคุณไม่เพียง แต่ไม่ถูกต้อง แต่ยังสร้างความสับสนให้กับผู้เริ่มต้น (คนที่ถามคำถามนี้)
PerformanceDBA

0
  • --- หนึ่งต่อหลาย --- พ่อแม่สามารถมีลูกสองคนขึ้นไป
  • --- หลายต่อหนึ่ง --- เด็กทั้ง 3 คนสามารถมีพ่อหรือแม่คนเดียวได้

    ทั้งสองมีความคล้ายคลึงกัน สิ่งนี้สามารถใช้ได้ตามความต้องการ หากคุณต้องการหาลูกให้กับผู้ปกครองคนใดคนหนึ่งคุณสามารถเลือกแบบตัวต่อตัว ไม่เช่นนั้นหากต้องการหาพ่อแม่ลูกแฝดคุณอาจไปกับ Many-To-One ในทำนองเดียวกัน ....


-6

one-to-manyมีคลาสพาเรนต์ที่มีจำนวนเด็ก n ดังนั้นจึงเป็นการแมปคอลเลคชัน

หลายต่อหนึ่งมีจำนวนลูกที่มีผู้ปกครองหนึ่งคนดังนั้นจึงเป็นการแมปวัตถุ


คำตอบนี้ดีและมีข้อมูลเพิ่มเติมไม่เข้าใจว่าเหตุใดจึงถูกโหวตลงในบริบทแบบทิศทางเดียวหนึ่งต่อหลายคนและหลายต่อหนึ่งจะไม่ให้คุณภาพของรหัสเดียวกันทั้งนี้ขึ้นอยู่กับ UX: หากคุณต้องการชุดข้อมูลที่เกี่ยวข้อง ดังนั้นหนึ่งถึงหลายคนฉลาดกว่าหากคุณไม่จำเป็นต้องมีคำสั่ง select ซึ่งเงื่อนไขบางอย่างก็ใช้ได้เพราะชุดนั้นอยู่ในแผนที่อย่างไรก็ตามหากผู้ใช้ไม่จำเป็นต้องรับชุดข้อมูลและสนใจแต่ละแถวในลักษณะเฉพาะ อินสแตนซ์ที่ต้องการดังนั้นหลายต่อหนึ่งจึงเป็นทางเลือกที่ชาญฉลาดกว่า
Mohammed Housseyn Taleb

อาจเป็นคำตอบที่ดี แต่ไม่เหมือนกัน: แบบกลุ่มต่อหนึ่งมีคลาสผู้ปกครองที่มีจำนวนลูกจำนวนหนึ่งตัวต่อกลุ่มมีผู้ปกครองหลายคนต่อเด็กหนึ่งคน ใน SQL อาจไม่สร้างความแตกต่างเนื่องจากความสัมพันธ์แบบกลุ่มต่อหนึ่งสามารถเป็นแบบรอบทิศทางได้ แต่ในกรอบเช่น Django นี่เป็นประเด็นสำคัญเนื่องจากไม่มีความสัมพันธ์แบบหนึ่งต่อกลุ่มและคีย์ต่างประเทศซึ่ง เกี่ยวข้องกับความสัมพันธ์แบบกลุ่มต่อหนึ่งทำงานตามธรรมชาติในทิศทางเดียวเท่านั้นไม่สามารถใช้วิธีอื่นในลักษณะเดียวกันได้
iFunction
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.