คำอธิบายของการเข้าร่วมด้วยตนเอง


87

ฉันไม่เข้าใจความจำเป็นในการเข้าร่วมด้วยตนเอง ใครช่วยอธิบายให้ฉันฟังหน่อยได้ไหม

ตัวอย่างง่ายๆจะเป็นประโยชน์มาก

คำตอบ:


99

คุณสามารถดูการเข้าร่วมด้วยตนเองเป็นตารางที่เหมือนกันสองตาราง แต่ในการทำให้เป็นมาตรฐานคุณไม่สามารถสร้างสองสำเนาของตารางได้ดังนั้นคุณเพียงแค่จำลองการมีสองตารางด้วยการเข้าร่วมด้วยตนเอง

สมมติว่าคุณมีสองตาราง:

ตาราง emp1

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

ตาราง emp2

Id Name Boss_id            
1   ABC   3                   
2   DEF   1                   
3   XYZ   2                   

ตอนนี้หากคุณต้องการรับชื่อพนักงานแต่ละคนพร้อมชื่อเจ้านายของเขา:

select c1.Name , c2.Name As Boss
from emp1 c1
    inner join emp2 c2 on c1.Boss_id = c2.Id

ซึ่งจะแสดงผลตารางต่อไปนี้:

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF

1
ในตัวอย่างนี้ฉันคิดไม่ออกว่าใครเป็นเจ้านาย แม้ว่าประสบการณ์จะดีและเข้าใจง่าย
MAC

2
left joinฉันคิดว่าจะดีกว่าถ้าไม่ทิ้งพนักงาน (หรือเจ้านาย) ที่ไม่มีเจ้านาย สุดยอดสุนัข!
Rockin4Life33

ควรมาจาก emp c1 แทนที่จะเป็น emp1 c1 หรือไม่? @pointlesspolitics
Rohit Singh

22

เป็นเรื่องปกติธรรมดาเมื่อคุณมีตารางที่อ้างอิงตัวเอง ตัวอย่าง: ตารางพนักงานที่พนักงานทุกคนสามารถมีผู้จัดการได้และคุณต้องการแสดงรายชื่อพนักงานทั้งหมดและชื่อผู้จัดการของพวกเขา

SELECT e.name, m.name
FROM employees e LEFT OUTER JOIN employees m
ON e.manager = m.id

18

การเข้าร่วมด้วยตนเองคือการร่วมโต๊ะกับตัวเอง

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

SELECT Child.ID, Child.Name, Child.PhoneNumber, Father.Name, Father.PhoneNumber
FROM myTableOfPersons As Child
LEFT OUTER JOIN  myTableOfPersons As Father ON Child.FatherId = Father.ID
WHERE Child.City = 'Chicago'  -- Or some other condition or none

เราสามารถรับข้อมูลเกี่ยวกับทั้งเด็กและพ่อ (และแม่ด้วยการเข้าร่วมด้วยตนเองครั้งที่สอง ฯลฯ และแม้แต่ผู้ปกครองที่ยิ่งใหญ่ ฯลฯ ...


5

สมมติว่าคุณมีโต๊ะusersตั้งค่าดังนี้:

  • ID ผู้ใช้
  • ชื่อผู้ใช้
  • ID ผู้จัดการของผู้ใช้

ในสถานการณ์นี้หากคุณต้องการดึงทั้งข้อมูลของผู้ใช้และข้อมูลของผู้จัดการออกมาในแบบสอบถามเดียวคุณสามารถทำได้:

SELECT users.user_id, users.user_name, managers.user_id AS manager_id, managers.user_name AS manager_name INNER JOIN users AS manager ON users.manager_id=manager.user_id

4

จะมีประโยชน์หากโต๊ะของคุณอ้างอิงตัวเอง ตัวอย่างเช่นสำหรับตารางของหน้าแต่ละหน้าอาจมีลิงก์nextและ previousซึ่งจะเป็นรหัสของเพจอื่น ๆ ในตารางเดียวกัน ถ้าในบางจุดที่คุณต้องการที่จะได้รับสามหน้าต่อเนื่องคุณจะทำสองด้วยตนเองร่วมในnextและpreviousคอลัมน์ที่มีตารางเดียวกันของidคอลัมน์


4

ลองนึกภาพตารางที่เรียกEmployeeตามที่อธิบายไว้ด้านล่าง พนักงานทุกคนมีผู้จัดการซึ่งเป็นพนักงานด้วย (อาจจะยกเว้น CEO ซึ่ง manager_id จะเป็นโมฆะ)

Table (Employee): 

int id,
varchar name,
int manager_id

จากนั้นคุณสามารถใช้ตัวเลือกต่อไปนี้เพื่อค้นหาพนักงานและผู้จัดการทั้งหมด:

select e1.name, e2.name as ManagerName
from Employee e1, Employee e2 where
where e1.manager_id = e2.id

4

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


แต่ตอนนี้คุณ (หวังว่า) จะเข้าใจว่าจะเกิดอะไรขึ้นหากไม่มีการอ้างอิงตัวเอง
ยูจีน

4

นอกเหนือจากคำตอบที่กล่าวมาแล้ว (ซึ่งอธิบายได้ดีมาก) ฉันต้องการเพิ่มอีกหนึ่งตัวอย่างเพื่อให้สามารถแสดงการใช้ Self Join ได้อย่างง่ายดาย สมมติว่าคุณมีตารางชื่อ CUSTOMERS ซึ่งมีแอตทริบิวต์ต่อไปนี้ CustomerID, CustomerName, ContactName, City, Country ตอนนี้คุณต้องการรายชื่อผู้ที่มาจาก "เมืองเดียวกัน" ทั้งหมด คุณจะต้องนึกถึงแบบจำลองของตารางนี้เพื่อให้เราสามารถเข้าร่วมได้บนพื้นฐานของ CITY ข้อความค้นหาด้านล่างจะแสดงให้เห็นอย่างชัดเจนว่าหมายถึงอะไร:

SELECT A.CustomerName AS CustomerName1, B.CustomerName AS CustomerName2, 
A.City
FROM Customers A, Customers B
WHERE A.CustomerID <> B.CustomerID
AND A.City = B.City 
ORDER BY A.City;

3
+1 คำตอบนี้มีความสำคัญมากเนื่องจากมีคำถามเกี่ยวกับ SQL จำนวนมากใน SO ซึ่งคำตอบคือ "ใช้การเข้าร่วมด้วยตนเอง" ซึ่งผู้คนมักจะมองไม่เห็นเมื่อไม่มีการอ้างอิงตนเองอย่างชัดเจน (ตามลำดับชั้น)
JimmyB

1
แม้ว่านี่จะเป็นพาสต้าคัดลอกจาก w3schools ฉันคิดว่าคำตอบข้างต้นไม่ได้อธิบายถึงการเข้าร่วมด้วยตนเอง แต่เป็นการเข้าร่วมภายในซึ่งแตกต่างกัน
George K

3

มีคำตอบที่ถูกต้องมากมายที่นี่ แต่มีรูปแบบที่ถูกต้องเท่าเทียมกัน คุณสามารถวางเงื่อนไขการเข้าร่วมของคุณในคำสั่งการเข้าร่วมแทนคำสั่ง WHERE ได้

SELECT e1.emp_id AS 'Emp_ID'
  , e1.emp_name AS 'Emp_Name'
  , e2.emp_id AS 'Manager_ID'
  , e2.emp_name AS 'Manager_Name'
FROM Employee e1 RIGHT JOIN Employee e2 ON e1.emp_id = e2.emp_id

โปรดทราบว่าบางครั้งคุณต้องการ e1.manager_id> e2.id

ข้อดีของการรู้ทั้งสองสถานการณ์คือบางครั้งคุณมีเงื่อนไข WHERE หรือ JOIN มากมายและคุณต้องการวางเงื่อนไขการเข้าร่วมด้วยตนเองในส่วนคำสั่งอื่น ๆ เพื่อให้โค้ดของคุณอ่านได้

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

ลองลูกสุนัขตัวนี้

SELECT e1.emp_id AS 'Emp_ID'
   , e1.emp_name AS 'Emp_Name'
   , e2.emp_id AS 'Manager_ID'
   , e2.emp_name AS 'Manager_Name'
FROM Employee e1 LEFT JOIN Employee e2 
   ON e1.emp_id = e2.emp_id
   AND e1.emp_name = e2.emp_name
   AND e1.every_other_matching_column = e2.every_other_matching_column

1
หืมในลูกสุนัขทำไมคุณเข้าร่วม "มากกว่า" แทนที่จะเป็น "เท่ากับ" ล่ะ?
Marcel

1
สวัสดี. ฉันเคยเห็นว่าบางตัวอย่างใช้ "FROM xxx, yyy WHERE" และ "FROM xxx JOIN yyy WHERE" อื่น ๆ คุณช่วยอธิบายความแตกต่างได้ไหม
กัน

@Skan นั่นเป็นคำถามที่ดีจริงๆ คำตอบสั้น ๆ คือเป็นวิธีการชวเลขแบบเก่าและจะเลิกใช้งาน ฉันใช้มันในโรงเรียนเมื่อสิบปีก่อนและไม่ค่อยเห็นมันในทางปฏิบัติ นี่คือคำอธิบายที่กระชับที่สุดที่ฉันสามารถหาได้: bidn.com/blogs/KathiKellenberger/sql-server/2875/…
BClaydon

1

กรณีการใช้งานหนึ่งกำลังตรวจหาเรกคอร์ดที่ซ้ำกันในฐานข้อมูล

SELECT A.Id FROM My_Bookings A, My_Bookings B
WHERE A.Name = B.Name
AND A.Date = B.Date
AND A.Id != B.Id

การใช้ GROUP BY และ HAVING clause เพื่อค้นหารายการที่ซ้ำกันเร็วกว่ามาก เลือกชื่ออีเมล COUNT ( ) จาก My_Bookings GROUP ตามชื่อวันที่ HAVING COUNT ( )> 1
George K

@GeorgeK จริง. ฉันคิดว่านี่เป็นสิ่งที่จำเป็นสำหรับการจับคู่ที่คลุมเครือเท่านั้น (นอกเหนือจากการจัดกลุ่มตาม TRIM (LOWER (ชื่อ))) และไม่ใช่เพื่อความเท่าเทียมที่เข้มงวด
Molossus Spondee

1

การเข้าร่วมด้วยตนเองมีประโยชน์เมื่อคุณต้องประเมินข้อมูลของตารางด้วยตัวมันเอง ซึ่งหมายความว่ามันจะสัมพันธ์แถวจากตารางเดียวกัน

Syntax: SELECT * FROM TABLE t1, TABLE t2 WHERE t1.columnName = t2.columnName

ตัวอย่างเช่นเราต้องการค้นหาชื่อของพนักงานที่ Initial Designation เท่ากับการกำหนดปัจจุบัน เราสามารถแก้ปัญหานี้ได้โดยใช้การเข้าร่วมด้วยตนเองตามวิธีต่อไปนี้

SELECT NAME FROM Employee e1, Employee e2 WHERE e1.intialDesignationId = e2.currentDesignationId

0

เป็นฐานข้อมูลที่เทียบเท่ากับรายการ / โครงสร้างที่เชื่อมโยงโดยที่แถวมีการอ้างอิงในความสามารถบางส่วนไปยังแถวอื่น


อันที่จริงเนื่องจากมีมากกว่าหนึ่งแถวที่สามารถอ้างอิง "พาเรนต์" ได้จึงอาจเป็นโครงสร้างได้เช่นกันเช่นกับตัวอย่างที่อ้างถึงของพนักงาน -> ผู้จัดการ
NVRAM

ฉันแค่พยายามเปรียบเทียบง่ายๆ แต่ก็ใช่ว่าต้นไม้ก็ใช้ได้เช่นกัน
Unsliced

-4

นี่คือการ Exaplanation ของการเข้าร่วมด้วยตนเองในแง่ของคนธรรมดา การเข้าร่วมด้วยตนเองไม่ใช่การเข้าร่วมประเภทอื่น หากคุณเข้าใจการเข้าร่วมประเภทอื่น ๆ แล้ว (Inner, Outer และ Cross Joins) การเข้าร่วมด้วยตนเองควรตรงไปตรงมา ใน INNER, OUTER และ CROSS JOINS คุณเข้าร่วม 2 ตารางขึ้นไป อย่างไรก็ตามในการเข้าร่วมด้วยตนเองคุณจะเข้าร่วมโต๊ะเดียวกันกับมัน ที่นี่เราไม่มีตาราง 2 ตาราง แต่ถือว่าตารางเดียวกันเป็นตารางอื่นโดยใช้ชื่อแทนตาราง หากยังไม่ชัดเจนฉันขอแนะนำให้ดูวิดีโอ youtube ต่อไปนี้

เข้าร่วมด้วยตนเองด้วยตัวอย่าง

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