Giải thích về tự kết hợp


84

Tôi không hiểu sự cần thiết của việc tự tham gia. Ai đó có thể vui lòng giải thích chúng cho tôi không?

Một ví dụ đơn giản sẽ rất hữu ích.

Câu trả lời:


95

Bạn có thể xem tự tham gia như hai bảng giống nhau. Nhưng trong quá trình chuẩn hóa, bạn không thể tạo hai bản sao của bảng vì vậy bạn chỉ cần mô phỏng việc có hai bảng với tính năng tự nối.

Giả sử bạn có hai bảng:

Bàn emp1

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

Bàn emp2

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

Bây giờ, nếu bạn muốn lấy tên của từng nhân viên với tên của sếp của họ:

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

Cái nào sẽ xuất ra bảng sau:

Name  Boss
ABC   XYZ
DEF   ABC
XYZ   DEF

1
Trong ví dụ này, tôi không thể tìm ra ai là ông chủ. Mặc dù điểm kinh nghiệm là tốt và dễ hiểu.
MAC

2
left joinTôi nghĩ sẽ tốt hơn nếu không nên bỏ nhân viên (hoặc sếp) không có sếp; con chó hàng đầu!
Rockin4Life33

22

Nó khá phổ biến khi bạn có một bảng tự tham chiếu. Ví dụ: một bảng nhân viên trong đó mọi nhân viên đều có thể có một người quản lý và bạn muốn liệt kê tất cả các nhân viên và tên của người quản lý của họ.

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

18

Một phép nối tự là phép nối một bảng với chính nó.

Một trường hợp sử dụng phổ biến là khi bảng lưu trữ các thực thể (bản ghi) có mối quan hệ phân cấp giữa chúng . Ví dụ: một bảng chứa thông tin người (Tên, DOB, Địa chỉ ...) và bao gồm một cột trong đó ID của Cha (và / hoặc của mẹ) được bao gồm. Sau đó, với một truy vấn nhỏ như

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

chúng ta có thể nhận thông tin về cả con và cha (và mẹ, với tự tham gia thứ hai, v.v. và thậm chí cả ông bà ngoại, v.v.) trong cùng một truy vấn.


5

Giả sử bạn có một bàn users, được thiết lập như vậy:

  • tên người dùng
  • tên tài khoản
  • ID của người quản lý của người dùng

Trong trường hợp này, nếu bạn muốn lấy ra cả thông tin của người dùng thông tin của người quản lý trong một truy vấn, bạn có thể làm như sau:

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

Chúng hữu ích nếu bảng của bạn tự tham chiếu. Ví dụ, đối với một bảng các trang, mỗi trang có thể có một nextpreviousliên kết. Đây sẽ là ID của các trang khác trong cùng một bảng. Nếu tại một thời điểm nào đó bạn muốn nhận được ba trang liên tiếp, bạn sẽ thực hiện hai phép tự nối trên các cột nextpreviouscột có cùng idcột của bảng .


4

Hãy tưởng tượng một bảng được gọi Employeenhư mô tả bên dưới. Tất cả nhân viên đều có người quản lý cũng là nhân viên (có thể ngoại trừ Giám đốc điều hành, người có manager_id sẽ là null)

Table (Employee): 

int id,
varchar name,
int manager_id

Sau đó, bạn có thể sử dụng lựa chọn sau để tìm tất cả nhân viên và người quản lý của họ:

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

4

Nếu không có khả năng bảng tự tham chiếu, chúng ta sẽ phải tạo càng nhiều bảng cho các mức phân cấp bằng số lớp trong hệ thống phân cấp. Nhưng vì chức năng đó có sẵn, bạn nối bảng với chính nó và sql coi nó như hai bảng riêng biệt, vì vậy mọi thứ được lưu trữ độc đáo ở một nơi.


nhưng bây giờ bạn (hy vọng) hiểu điều gì sẽ xảy ra nếu tài liệu tự tham khảo không có sẵn.
Eugene

4

Ngoài các câu trả lời được đề cập ở trên (đã được giải thích rất rõ ràng), tôi muốn thêm một ví dụ để có thể dễ dàng chỉ ra việc sử dụng Self Join. Giả sử bạn có một bảng tên là CUSTOMERS có các thuộc tính sau: CustomerID, CustomerName, ContactName, City, Country. Bây giờ bạn muốn liệt kê tất cả những người đến từ "cùng một thành phố". Bạn sẽ phải nghĩ ra một bản sao của bảng này để chúng tôi có thể tham gia cùng họ trên cơ sở CITY. Truy vấn bên dưới sẽ hiển thị rõ ràng ý nghĩa của nó:

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 Câu trả lời này rất quan trọng vì có rất nhiều câu hỏi SQL trên SO mà câu trả lời là "sử dụng tự nối", mà mọi người có xu hướng không nhìn thấy khi họ không có tham chiếu bản thân (phân cấp) rõ ràng.
JimmyB,

1
Ngay cả khi đây là mì ống sao chép từ w3schools, tôi nghĩ câu trả lời ở trên không giải thích về self-join mà là internal-join thì khác.
George K

3

Có nhiều câu trả lời đúng ở đây, nhưng có một biến thể cũng đúng như nhau. Bạn có thể đặt các điều kiện tham gia của mình trong câu lệnh tham gia thay vì mệnh đề 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

Hãy nhớ rằng đôi khi bạn muốn e1.manager_id> e2.id

Lợi thế của việc biết cả hai trường hợp là đôi khi bạn có rất nhiều điều kiện WHERE hoặc JOIN và bạn muốn đặt các điều kiện tự tham gia của mình trong mệnh đề khác để giữ cho mã của bạn có thể đọc được.

Không ai giải quyết điều gì sẽ xảy ra khi Nhân viên không có người quản lý. Huh? Chúng không được bao gồm trong tập kết quả. Điều gì sẽ xảy ra nếu bạn muốn bao gồm nhân viên không có người quản lý nhưng bạn không muốn trả về các kết hợp không chính xác?

Hãy thử con chó con này;

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
Hm, trong con chó con, tại sao bạn lại tham gia vào "lớn hơn" thay vì "bằng"?
Marcel

1
Chào. Tôi đã thấy rằng một số ví dụ sử dụng "FROM xxx, yyy WHERE" và một số khác "FROM xxx JOIN yyy WHERE". Xin vui lòng giải thích sự khác biệt, xin vui lòng?
skan

@Skan Đó là một câu hỏi thực sự hay. Câu trả lời ngắn gọn là đó là phương pháp tốc ký cũ và sẽ không được dùng nữa. Tôi đã sử dụng nó ở trường hơn 10 năm trước và hiếm khi thấy nó trong thực tế. Đây là mô tả ngắn gọn nhất mà tôi có thể tìm thấy: bidn.com/blogs/KathiKellenberger/sql-server/2875/…
BClaydon

1

Một trường hợp sử dụng là kiểm tra các bản ghi trùng lặp trong cơ sở dữ liệu.

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

Việc sử dụng GROUP BY và mệnh đề HAVING để tìm các bản sao sẽ nhanh hơn nhiều. Tên SELECT, email, COUNT ( ) TỪ My_Bookings GROUP tên BY, HAVING ngày COUNT ( )> 1
George K

@GeorgeK Đúng. Tôi cho rằng điều này chỉ cần thiết cho một trận đấu mờ (ngoài nhóm theo TRIM (LOWER (Tên))) và không phải cho sự bình đẳng nghiêm ngặt.
Steven Stewart-Gallus

1

Tự tham gia rất hữu ích khi bạn phải đánh giá dữ liệu của bảng với chính nó. Có nghĩa là nó sẽ tương quan với các hàng trong cùng một bảng.

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

Ví dụ: chúng tôi muốn tìm tên của những nhân viên có Chỉ định ban đầu bằng với chỉ định hiện tại. Chúng ta có thể giải quyết vấn đề này bằng cách sử dụng self join theo cách sau.

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

0

Đó là cơ sở dữ liệu tương đương với một danh sách / cây được liên kết, trong đó một hàng chứa một tham chiếu với một số khả năng cho một hàng khác.


Trên thực tế, cho rằng nhiều hơn một hàng có thể tham chiếu đến một "cha", nó cũng có thể là một cây, chẳng hạn như với ví dụ trích dẫn oft về worker-> manager.
NVRAM

Tôi chỉ đang thử một phép loại suy đơn giản, nhưng đúng là một cái cây cũng có thể hoạt động.
Unliced

-4

Đây là sự tôn sùng bản thân trong các thuật ngữ giáo dân. Tự tham gia không phải là một loại tham gia khác. Nếu bạn đã hiểu các loại liên kết khác (Tham gia bên trong, Bên ngoài và Kết hợp chéo), thì tự tham gia nên được chuyển tiếp. Trong INNER, OUTER và CROSS JOINS, bạn tham gia 2 hoặc nhiều bảng khác nhau. Tuy nhiên, tự tham gia, bạn tham gia cùng một bàn với itlef. Ở đây, chúng ta không có 2 bảng khác nhau, nhưng coi cùng một bảng như một bảng khác bằng cách sử dụng bí danh bảng. Nếu điều này vẫn chưa rõ ràng, tôi khuyên bạn nên xem các video youtube sau.

Tự tham gia với một ví dụ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.