Sự khác biệt giữa tham gia tự nhiên và tham gia bên trong


197

Sự khác biệt giữa tham gia tự nhiên và tham gia bên trong là gì?


3
Câu hỏi này không phải là một bản sao của câu hỏi khác, vì đây là về việc tham gia INNER vs NATURAL, không được đề cập trong câu hỏi khác.

1
Tại một thời điểm, điều này đã được đóng lại như một bản sao của Sự khác biệt giữa các liên kết trái, phải, bên ngoài và bên trong , nhưng câu hỏi đó không giải quyết được sự khác biệt giữa các phép nối bên trong và phép nối tự nhiên.
Jonathan Leffler

Câu trả lời:


250

Một sự khác biệt đáng kể giữa INNER THAM GIA và THAM GIA TỰ NHIÊN là số lượng cột được trả về.

Xem xét:

TableA                           TableB
+------------+----------+        +--------------------+    
|Column1     | Column2  |        |Column1  |  Column3 |
+-----------------------+        +--------------------+
| 1          |  2       |        | 1       |   3      |
+------------+----------+        +---------+----------+

Bảng INNER JOINTableA và TableB trên Cột1 sẽ trả về

SELECT * FROM TableA AS a INNER JOIN TableB AS b USING (Column1);
SELECT * FROM TableA AS a INNER JOIN TableB AS b ON a.Column1 = b.Column1;
+------------+-----------+---------------------+    
| a.Column1  | a.Column2 | b.Column1| b.Column3|
+------------------------+---------------------+
| 1          |  2        | 1        |   3      |
+------------+-----------+----------+----------+

Bảng NATURAL JOINTableA và TableB trên Cột1 sẽ trả về:

SELECT * FROM TableA NATURAL JOIN TableB
+------------+----------+----------+    
|Column1     | Column2  | Column3  |
+-----------------------+----------+
| 1          |  2       |   3      |
+------------+----------+----------+

Cột lặp lại được tránh.

(AFAICT từ ngữ pháp chuẩn, bạn không thể chỉ định các cột tham gia trong một phép nối tự nhiên; phép nối này hoàn toàn dựa trên tên. Xem thêm Wikipedia .)

( Có một cheat trong liên kết nội đầu ra; các a.b.phụ tùng sẽ không có trong tên cột, bạn sẽ chỉ có column1, column2, column1, column3như các tiêu đề. )


2
Tôi có hai bảng TableA (Cột1, Cột2) và BảngB (Cột2, Cột3).
2 8

16
Thu gọn các cột trong đầu ra là khía cạnh ít quan trọng nhất của phép nối tự nhiên. Những điều bạn cần biết là (A) nó sẽ tự động tham gia vào các trường có cùng tên và (B) nó sẽ tăng tốc cho bạn khi bạn ít mong đợi nhất. Trong thế giới của tôi, sử dụng một tham gia tự nhiên là căn cứ để sa thải.

8
@Jonof ALLTrades Bạn có thể giải thích thêm về chính xác những gì NATURAL JOINsẽ hủy hoại, tại sao nó bất ngờ, và bạn đang ở thế giới nào?
Bryson

35
Điều này được giải quyết phần nào trong câu trả lời của user166390. Nói rằng bạn có một sự tham gia tự nhiên giữa CustomersEmployees, tham gia vào EmployeeID. Employeescũng có một ManagerIDlĩnh vực. Mọi thứ đều ổn. Sau đó, một ngày nào đó, một người nào đó thêm một ManagerIDlĩnh vực vào Customersbàn. Sự tham gia của bạn sẽ không bị phá vỡ (đó sẽ là một sự thương xót), thay vào đó giờ đây nó sẽ bao gồm một trường thứ hai và hoạt động không chính xác . Do đó, một sự thay đổi dường như vô hại có thể phá vỡ một cái gì đó chỉ liên quan đến xa. RẤT TỆ. Mặt trái duy nhất của một phép nối tự nhiên là tiết kiệm một chút gõ và nhược điểm là đáng kể.

2
@Jonathan, Về câu trả lời của bạn, bạn đã nêu rằng SELECT * FROM TableA INNER JOIN TableB USING (Column1)đưa ra 4 cột. Điều này không đúng vì SELECT * FROM TableA INNER JOIN TableB USING (Column1)SELECT * FROM TableA NATURAL JOIN TableBbằng nhau, cả hai đều cho 3 cột.
Pacerier

81
  • Tham gia bên trong là một liên kết trong đó hàng phù hợp trong bảng đã tham gia được yêu cầu cho một hàng từ bảng đầu tiên được trả về
  • Một kết nối bên ngoài là một trong đó không yêu cầu hàng phù hợp trong bảng đã tham gia cho một hàng từ bảng đầu tiên được trả về
  • Tham gia tự nhiên là tham gia (bạn có thể có natural lefthoặc natural right) giả định tiêu chí tham gia là nơi các cột có cùng tên trong cả hai bảng khớp

Tôi sẽ tránh sử dụng các phép nối tự nhiên như bệnh dịch hạch, bởi vì các phép nối tự nhiên là:

  • không phải sql tiêu chuẩn [SQL 92] và do đó không khả chuyển, không đặc biệt dễ đọc (bởi hầu hết các lập trình viên SQL) và có thể không được hỗ trợ bởi các công cụ / thư viện khác nhau
  • không cung cấp thông tin; bạn không thể biết cột nào đang được nối mà không cần tham khảo lược đồ
  • điều kiện tham gia của bạn vô cùng dễ bị tổn thương trước các thay đổi lược đồ - nếu có nhiều cột tham gia tự nhiên và một cột như vậy bị xóa khỏi một bảng, truy vấn sẽ vẫn thực thi, nhưng có thể không chính xác và thay đổi hành vi này sẽ im lặng
  • hầu như không đáng nỗ lực; bạn chỉ tiết kiệm được khoảng 10 giây khi gõ

2
Tôi nghĩ rằng bên trái / bên phải cho bên ngoài nên được đề cập (vì bên ngoài được đề cập ở tất cả). Nhưng mặt khác, hay và súc tích: nó chỉ thiếu các sơ đồ bản ghi SQL đẹp.

2
TRÁI PHIẾU TỰ NHIÊN và QUYỀN TỰ NHIÊN cũng tồn tại. Nhưng có, vẫn tránh chúng.
MatBailie

1
@Bohantic, Về việc "tránh chúng như bệnh dịch", có những trường hợp sử dụng thực sự cho các phép nối tự nhiên nhờ đó chúng có ích. mariadb.com/kb/en/sql-99/natural-join "..." Sách "có vẻ giản dị NATURAL JOIN Checkoutschỉ có thể có khi các quy ước đặt tên cơ sở dữ liệu là chính thức và được thi hành ...."
Pacerier

2
@sqlvigs có rất nhiều sai với nhận xét của bạn, cụ thể là nó không chính xác. Các cột tham gia không thể được "chỉ định trong danh sách chọn". Định nghĩa của phép nối tự nhiên là tham gia vào * tất cả các cột có tên giống như *. Từ tài liệu MySQL: THAM GIA [TRÁI] TỰ NHIÊN của hai bảng được xác định là tương đương về mặt ngữ nghĩa với THAM GIA VÀ MỘT THAM GIA với mệnh đề SỬ DỤNG đặt tên cho tất cả các cột tồn tại trong cả hai bảng. . Và một điều nữa - trong thực tế, nó vô dụng, bởi vì idcó mặt ở khắp nơi và vô dụng để tham gia; tên khóa nước ngoài thông thường là tablename_id. Tham gia tự nhiên là một ý tưởng tồi, xấu, xấu.
Bohemian

2
Không có cột trả lại gấp đôi trong truy vấn của tôi. Một trong những lợi thế của ngữ nghĩa NJ là các cột trùng lặp không bao giờ được trả lại. Truy vấn trước đó của bạn cũng "kém an toàn" hơn so với của tôi vì sẽ không thành công nếu một cột có tên "a" được thêm vào t2 (vì điều kiện nối không bí danh là không rõ ràng). Tôi nghi ngờ rằng định kiến ​​của bạn đối với NJ dựa trên thực tế là bạn chưa từng thử nó trong một sản phẩm có SQL chuẩn được hỗ trợ đúng cách. Câu hỏi ở đây là về SQL, không phải MySQL - những thứ hoàn toàn khác. Bạn vẫn chưa sửa câu trả lời của mình về việc nó không chuẩn.
nvogel

27

Một phép nối tự nhiên chỉ là một phím tắt để tránh gõ, với giả định rằng phép nối này đơn giản và khớp với các trường cùng tên.

SELECT
  *
FROM
  table1
NATURAL JOIN
  table2
    -- implicitly uses `room_number` to join

Giống như ...

SELECT
  *
FROM
  table1
INNER JOIN
  table2
    ON table1.room_number = table2.room_number

Tuy nhiên, những gì bạn không thể làm với định dạng phím tắt là tham gia phức tạp hơn ...

SELECT
  *
FROM
  table1
INNER JOIN
  table2
    ON (table1.room_number = table2.room_number)
    OR (table1.room_number IS NULL AND table2.room_number IS NULL)

2
@JonathanLeffler - Trong MySQL, chắc chắn.
MatBailie

3
OK - thú vị. Tôi đã hỏi vì tiêu chuẩn SQL dường như không cho phép điều này (nhưng luôn có thể mở rộng).
Jonathan Leffler

DBMS nào cho phép cú pháp không chuẩn này : NATURAL JOIN ... USING ()? Tiêu chuẩn là a NATURAL JOIN bhoặca JOIN b USING (c)
ypercubeᵀᴹ

1
"Chỉ là một phím tắt để tránh gõ" là một sai lầm. Đặc điểm quan trọng nhất của nó là nó không dẫn đến các cột trùng lặp.
onedaywhen

... ví dụ: kết quả truy vấn của bạn sử dụng phép nối tự nhiên sẽ chỉ có một cột được đặt tên room_number, trong khi các phép nối bên trong của bạn sẽ có hai cột được đặt tên room_number.
onedaywhen

13

SQL không trung thành với mô hình quan hệ theo nhiều cách. Kết quả của một truy vấn SQL không phải là một mối quan hệ vì nó có thể có các cột có tên trùng lặp, cột 'ẩn danh' (không tên), hàng trùng lặp, null, v.v. SQL không coi các bảng là quan hệ vì nó phụ thuộc vào thứ tự cột, v.v.

Ý tưởng đằng sau NATURAL JOINtrong SQL là làm cho nó dễ dàng trung thành hơn với mô hình quan hệ. Kết quả của NATURAL JOINhai bảng sẽ có các cột được nhân đôi theo tên, do đó không có cột ẩn danh. Tương tự, UNION CORRESPONDINGEXCEPT CORRESPONDINGđược cung cấp để giải quyết sự phụ thuộc của SQL vào thứ tự cột trong UNIONcú pháp kế thừa .

Tuy nhiên, như với tất cả các kỹ thuật lập trình, nó đòi hỏi kỷ luật phải hữu ích. Một yêu cầu để thành công NATURAL JOINlà các cột được đặt tên nhất quán, bởi vì các phép nối được ngụ ý trên các cột có cùng tên (điều đáng tiếc là cú pháp đổi tên cột trong SQL là dài dòng nhưng tác dụng phụ là khuyến khích kỷ luật khi đặt tên cột trong bảng cơ sở và VIEWs :)

Lưu ý rằng SQL NATURAL JOINlà một đẳng thức **, tuy nhiên điều này không có ích gì. Hãy xem xét rằng nếu NATURAL JOINlà loại tham gia duy nhất được hỗ trợ trong SQL thì nó vẫn hoàn toàn tương đối .

Mặc dù thực sự là bất kỳ NATURAL JOINcó thể được viết bằng cách sử dụng INNER JOINvà chiếu ( SELECT), nhưng cũng đúng là bất kỳ INNER JOINcó thể được viết bằng cách sử dụng sản phẩm ( CROSS JOIN) và hạn chế ( WHERE); lưu ý thêm rằng NATURAL JOINgiữa các bảng không có tên cột chung sẽ cho kết quả giống như CROSS JOIN. Vì vậy, nếu bạn chỉ quan tâm đến kết quả là quan hệ (và tại sao không bao giờ?!) Thì đây NATURAL JOINlà loại tham gia duy nhất bạn cần. Chắc chắn, sự thật là từ góc độ thiết kế ngôn ngữ như viết tắt INNER JOINCROSS JOINcó giá trị của chúng, nhưng cũng xem xét rằng hầu như mọi truy vấn SQL đều có thể được viết bằng 10 cách khác nhau về mặt cú pháp, nhưng tương đương về mặt ngữ nghĩa và đây là điều khiến cho việc tối ưu hóa SQL rất khó khăn phát triển.

Dưới đây là một số truy vấn mẫu (sử dụng cơ sở dữ liệu bộ phận và nhà cung cấp thông thường ) tương đương về mặt ngữ nghĩa:

SELECT *
  FROM S NATURAL JOIN SP;

-- Must disambiguate and 'project away' duplicate SNO attribute
SELECT S.SNO, SNAME, STATUS, CITY, PNO, QTY
  FROM S INNER JOIN SP 
          USING (SNO);                        

-- Alternative projection
SELECT S.*, PNO, QTY
  FROM S INNER JOIN SP 
          ON S.SNO = SP.SNO;

-- Same columns, different order == equivalent?!
SELECT SP.*, S.SNAME, S.STATUS, S.CITY
  FROM S INNER JOIN SP 
      ON S.SNO = SP.SNO;

-- 'Old school'
SELECT S.*, PNO, QTY
  FROM S, SP 
 WHERE S.SNO = SP.SNO;

** Tham gia tự nhiên quan hệ không phải là một Equijoin, nó là một hình chiếu của một. - philipxy


Tham gia tự nhiên quan hệ không phải là một Equijoin, nó là một hình chiếu của một. SQL tự nhiên tham gia là một Equijoin SQL (có thể trùng lặp) - nó được định nghĩa theo cách sử dụng tham gia bên trong.
philipxy

@philipxy: Cảm ơn, tôi đã sửa đổi. Xin vui lòng chỉnh sửa - điều này hoặc bất kỳ câu trả lời của tôi - cho những sai lầm và hiểu lầm. Tôi vẫn đang học hỏi từ bạn :)
onedaywhen

9

Tham NATURALgia chỉ là một cú pháp ngắn cho một liên kết cụ thể INNER - hoặc "tham gia đẳng thức" - và, một khi cú pháp được mở ra, cả hai đều đại diện cho cùng một hoạt động Đại số quan hệ. Đây không phải là "loại khác nhau" của tham gia, như với trường hợp OUTER( LEFT/ RIGHT) hoặc CROSStham gia.

Xem phần bình đẳng trên Wikipedia:

Một phép nối tự nhiên cung cấp một sự chuyên môn hóa hơn nữa của đẳng thức. Vị từ nối phát sinh ngầm bằng cách so sánh tất cả các cột trong cả hai bảng có cùng tên cột trong các bảng đã nối. Bảng tham gia kết quả chỉ chứa một cột cho mỗi cặp cột được đặt tên bằng nhau.

Hầu hết các chuyên gia đồng ý rằng THAM GIA TỰ NHIÊN là nguy hiểm và do đó không khuyến khích sử dụng chúng. Sự nguy hiểm đến từ việc vô tình thêm một cột mới, được đặt tên giống như một cột khác ...

Đó là, tất cả các phép NATURALnối có thể được viết dưới dạng phép INNERnối (nhưng điều ngược lại là không đúng). Để làm như vậy, chỉ cần tạo vị ngữ một cách rõ ràng - ví dụ USINGhoặc ON- và, như Jonathan Leffler đã chỉ ra, chọn các cột tập kết quả mong muốn để tránh "trùng lặp" nếu muốn.

Chúc mừng mã hóa.


( NATURALTừ khóa cũng có thể được áp dụng LEFTRIGHTtham gia, và áp dụng tương tự. Tham NATURAL LEFT/RIGHTgia chỉ là một cú pháp ngắn cho một tham gia cụ thể LEFT/RIGHT .)


2
"Tham gia TỰ NHIÊN chỉ là cú pháp ngắn cho [snipped]" Equi-jo "- và, một khi cú pháp chưa được mở, cả hai đều đại diện cho cùng một Đại số quan hệ" - bạn đã đúng: điều đó đúng với đại số quan hệ nhưng câu trả lời của bạn bị phá vỡ sau đó, ví dụ: "Hầu hết các chuyên gia đồng ý rằng THAM GIA TỰ NHIÊN là nguy hiểm và do đó không khuyến khích sử dụng chúng" - mà các chuyên gia trong đại số quan hệ nói rằng?!
onedaywhen

2

Tham gia tự nhiên: Đó là kết quả hoặc kết hợp của tất cả các cột trong hai bảng. Nó sẽ trả về tất cả các hàng của bảng đầu tiên đối với bảng thứ hai.

Tham gia bên trong: Tham gia này sẽ hoạt động trừ khi có bất kỳ tên cột nào được sxame trong hai bảng


3
Tôi không nghĩ câu trả lời của bạn đủ rõ ràng và sẽ viết lại lớn để sửa nó.
onedaywhen

0

Một tham gia tự nhiên là nơi 2 bảng được nối trên cơ sở của tất cả các cột phổ biến.

cột chung: là một cột có cùng tên trong cả hai bảng + có kiểu dữ liệu tương thích trong cả hai bảng. Bạn chỉ có thể sử dụng = toán tử

Tham gia bên trong là nơi 2 bảng được nối trên cơ sở các cột phổ biến được đề cập trong mệnh đề ON.

cột chung: là một cột có các kiểu dữ liệu tương thích trong cả hai bảng nhưng không cần phải có cùng tên. Bạn có thể chỉ sử dụng bất kỳ nhà điều hành so sánh như =, <=, >=, <, >,<>


-2

sự khác biệt là tham gia bên trong (đẳng thức / mặc định) và tham gia tự nhiên mà trong phần chung của cột tham gia natuarl sẽ được hiển thị trong một lần duy nhất nhưng bên trong / đẳng thức / mặc định / đơn giản, cột chung sẽ được hiển thị gấp đôi thời gian.


-2

Tham gia bên trong và tham gia tự nhiên gần như giống nhau nhưng có một chút khác biệt giữa chúng. Sự khác biệt là trong phép nối tự nhiên không cần chỉ định điều kiện nhưng trong điều kiện nối bên trong là bắt buộc. Nếu chúng ta chỉ định điều kiện trong phép nối bên trong, thì các bảng kết quả giống như một sản phẩm cartesian.


Tại sao không cần chỉ định điều kiện tham gia? Trong những trường hợp nào sẽ chỉ định các điều kiện trong một kết nối bên trong trong một cái gì đó giống như một sản phẩm cartesian?
onedaywhen

Gọi tham gia bên ngoài và bên trong "gần như giống nhau" là một imho understatement nhẹ .. có lẽ bạn có thể giải thích về đánh giá của bạn?
TMOTTM

-3
mysql> SELECT  * FROM tb1 ;
+----+------+
| id | num  |
+----+------+
|  6 |   60 |
|  7 |   70 |
|  8 |   80 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

mysql> SELECT  * FROM tb2 ;
+----+------+
| id | num  |
+----+------+
|  4 |   40 |
|  5 |   50 |
|  9 |   90 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

THAM GIA

mysql> SELECT  * FROM tb1 JOIN tb2 ; 
+----+------+----+------+
| id | num  | id | num  |
+----+------+----+------+
|  6 |   60 |  4 |   40 |
|  7 |   70 |  4 |   40 |
|  8 |   80 |  4 |   40 |
|  1 |    1 |  4 |   40 |
|  2 |    2 |  4 |   40 |
|  3 |    3 |  4 |   40 |
|  6 |   60 |  5 |   50 |
|  7 |   70 |  5 |   50 |
|  8 |   80 |  5 |   50 |
.......more......
return 36 rows in set (0.01 sec) 
AND NATURAL JOIN :

    mysql> SELECT  * FROM tb1 NATURAL JOIN tb2 ;
    +----+------+
    | id | num  |
    +----+------+
    |  1 |    1 |
    |  2 |    2 |
    |  3 |    3 |
    +----+------+
    3 rows in set (0.01 sec)

-4

Tham gia bên trong, tham gia hai bảng trong đó tên cột giống nhau.

Tham gia tự nhiên, tham gia hai bảng trong đó tên cột và kiểu dữ liệu giống nhau.


Điều này là hoàn toàn không chính xác. A NATURAL JOIN(như nhiều người đã chỉ ra nhiều năm trước) là một trong đó các tên cột giống nhau. Kiểu dữ liệu không cần phải giống nhau. Các trường được sử dụng cho một INNER JOINnhu cầu không có cùng tên.
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.