Ngoài ra làm thế nào LEFT JOIN, RIGHT JOINvà FULL JOINphù hợp với?
Ngoài ra làm thế nào LEFT JOIN, RIGHT JOINvà FULL JOINphù hợp với?
Câu trả lời:
Giả sử bạn đang tham gia trên các cột không có bản sao, đây là trường hợp rất phổ biến:
Một phép nối bên trong của A và B cho kết quả của A giao nhau B, tức là phần bên trong của giao điểm sơ đồ Venn .
Một phép nối ngoài của A và B cho kết quả của A union B, tức là các phần bên ngoài của liên kết sơ đồ Venn.
Ví dụ
Giả sử bạn có hai bảng, mỗi cột có một cột và dữ liệu như sau:
A B
- -
1 3
2 4
3 5
4 6
Lưu ý rằng (1,2) là duy nhất đối với A, (3,4) là phổ biến và (5,6) là duy nhất đối với B.
Tham gia nội bộ
Một phép nối bên trong bằng cách sử dụng một trong hai truy vấn tương đương sẽ cho giao điểm của hai bảng, tức là hai hàng chúng có chung.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
Tham gia bên ngoài bên trái
Một kết nối bên ngoài bên trái sẽ cho tất cả các hàng trong A, cộng với bất kỳ hàng phổ biến nào trong B.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
Tham gia bên ngoài bên phải
Một kết nối bên ngoài bên phải sẽ cho tất cả các hàng trong B, cộng với bất kỳ hàng phổ biến nào trong A.
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
Tham gia đầy đủ bên ngoài
Một phép nối ngoài đầy đủ sẽ cung cấp cho bạn liên kết của A và B, tức là tất cả các hàng trong A và tất cả các hàng trong B. Nếu một cái gì đó trong A không có mốc thời gian tương ứng trong B, thì phần B là null và ngược lại ngược lại
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
Các sơ đồ Venn không thực sự làm điều đó cho tôi.
Ví dụ, chúng không thể hiện bất kỳ sự phân biệt nào giữa liên kết chéo và liên kết nội bộ, hay nói chung hơn là cho thấy bất kỳ sự phân biệt nào giữa các loại vị từ tham gia khác nhau hoặc cung cấp một khung để suy luận về cách chúng sẽ hoạt động.
Không có thay thế cho việc hiểu xử lý logic và dù sao thì cũng tương đối đơn giản để nắm bắt.
onmệnh đề đối với tất cả các hàng từ bước 1 giữ những mệnh đề mà vị từ ước tínhtrue(NB: Trong thực tế, trình tối ưu hóa truy vấn có thể tìm thấy các cách thực hiện truy vấn hiệu quả hơn so với mô tả logic thuần túy ở trên nhưng kết quả cuối cùng phải giống nhau)
Tôi sẽ bắt đầu với một phiên bản hoạt hình của một tham gia bên ngoài đầy đủ . Giải thích thêm sau đây.
Bảng nguồn

Đầu tiên bắt đầu với một CROSS JOIN(Sản phẩm AKA Cartesian). Điều này không có một ONmệnh đề và chỉ đơn giản trả về mọi sự kết hợp của các hàng từ hai bảng.
CHỌN A.Colour, B.Colour TỪ MỘT CROSS THAM GIA B

Các phép nối bên trong và bên ngoài có một vị từ mệnh đề "BẬT".
CHỌN A.Colour, B.Colour TỪ MỘT NGƯỜI THAM GIA B ON A.Colour = B.Colour
Trên đây là Equi cổ điển tham gia.

Điều kiện nối bên trong không nhất thiết phải là điều kiện bằng và nó không cần tham chiếu các cột từ cả hai (hoặc thậm chí) của các bảng. Đánh giá A.Colour NOT IN ('Green','Blue')trên mỗi hàng của lợi nhuận tham gia chéo.

CHỌN A.Colour, B.Colour TỪ MỘT NGƯỜI THAM GIA B ONNG 1 = 1
Điều kiện nối ước tính là đúng cho tất cả các hàng trong kết quả nối chéo, vì vậy điều này giống như tham gia chéo. Tôi sẽ không lặp lại hình ảnh của 16 hàng một lần nữa.
Các liên kết ngoài được đánh giá logic theo cách tương tự như các phép nối bên trong ngoại trừ việc nếu một hàng từ bảng bên trái (đối với tham gia bên trái) không tham gia với bất kỳ hàng nào từ bảng bên phải, tất cả đều được giữ nguyên trong các kết quả với NULLcác giá trị cho cột bên tay phải.

Điều này chỉ đơn giản là hạn chế kết quả trước đó chỉ trả về các hàng trong đó B.Colour IS NULL. Trong trường hợp cụ thể này, đây sẽ là các hàng được bảo tồn vì chúng không có kết quả khớp trong bảng bên phải và truy vấn trả về hàng đỏ duy nhất không khớp trong bảng B. Điều này được gọi là một chống tham gia.
Điều quan trọng là chọn một cột cho IS NULLthử nghiệm không thể rỗng hoặc điều kiện nối đảm bảo rằng mọi NULLgiá trị sẽ được loại trừ để mẫu này hoạt động chính xác và tránh chỉ đưa các hàng trở lại có NULLgiá trị cho điều đó cột ngoài các hàng không khớp.

Các kết nối bên ngoài bên phải hoạt động tương tự như các liên kết bên ngoài bên trái ngoại trừ chúng bảo toàn các hàng không khớp từ bảng bên phải và null mở rộng các cột bên trái.

Các phép nối ngoài đầy đủ kết hợp hành vi của các phép nối trái và phải và giữ các hàng không khớp từ cả hai bảng bên trái và bên phải.

Không có hàng nào trong phép nối chéo khớp với 1=0vị ngữ. Tất cả các hàng từ cả hai phía được bảo tồn bằng các quy tắc nối ngoài bình thường với NULL trong các cột từ bảng ở phía bên kia.

Với một sửa đổi nhỏ cho truy vấn trước, người ta có thể mô phỏng một UNION ALLtrong hai bảng.

Lưu ý rằng WHEREmệnh đề (nếu có) chạy một cách hợp lý sau khi nối. Một lỗi phổ biến là thực hiện nối ngoài bên trái và sau đó bao gồm mệnh đề WHERE với một điều kiện trên bảng bên phải kết thúc không bao gồm các hàng không khớp. Ở trên kết thúc việc thực hiện tham gia bên ngoài ...

... Và sau đó mệnh đề "Ở đâu" chạy. NULL= 'Green'không đánh giá là đúng vì vậy hàng được bảo tồn bởi phép nối ngoài kết thúc bị loại bỏ (cùng với màu xanh) chuyển đổi hiệu quả phép nối trở lại thành liên kết bên trong.
Nếu ý định chỉ bao gồm các hàng từ B trong đó Màu là Xanh lục và tất cả các hàng từ A bất kể cú pháp đúng sẽ là

Xem các ví dụ này chạy trực tiếp tại SQLFiddle.com .
Các phép nối được sử dụng để kết hợp dữ liệu từ hai bảng, với kết quả là một bảng mới, tạm thời. Các phép nối được thực hiện dựa trên một thứ gọi là vị ngữ, trong đó chỉ định điều kiện sử dụng để thực hiện phép nối. Sự khác biệt giữa phép nối bên trong và phép nối ngoài là phép nối bên trong sẽ chỉ trả về các hàng thực sự khớp với nhau dựa trên vị từ nối. Ví dụ: Hãy xem xét bảng Nhân viên và Vị trí:

Tham gia bên trong: - Tham gia bên trong tạo bảng kết quả mới bằng cách kết hợp các giá trị cột của hai bảng ( Nhân viên và Vị trí ) dựa trên biến vị ngữ tham gia. Truy vấn so sánh từng hàng Nhân viên với từng hàng Vị trí để tìm tất cả các cặp hàng thỏa mãn vị ngữ tham gia. Khi vị từ tham gia được thỏa mãn bằng cách khớp các giá trị không phải NULL, các giá trị cột cho mỗi cặp hàng Nhân viên và Vị trí phù hợp sẽ được kết hợp thành một hàng kết quả. Đây là những gì SQL cho một tham gia bên trong sẽ trông như thế nào:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
Bây giờ, đây là kết quả của việc chạy SQL đó sẽ như thế nào:

Kết nối ngoài: - Một phép nối ngoài không yêu cầu mỗi bản ghi trong hai bảng đã nối phải có bản ghi khớp. Bảng đã tham gia giữ lại từng bản ghi ngay cả khi không có bản ghi khớp nào khác tồn tại. Các liên kết ngoài chia nhỏ hơn nữa thành các liên kết ngoài bên trái và các liên kết ngoài bên phải, tùy thuộc vào các hàng của bảng được giữ lại (trái hoặc phải).
Tham gia bên ngoài bên trái: - Kết quả của việc tham gia bên ngoài bên trái (hoặc đơn giản là tham gia bên trái) cho các bảng Nhân viên và Vị trí luôn chứa tất cả các bản ghi của bảng "bên trái" ( Nhân viên ), ngay cả khi điều kiện tham gia không tìm thấy bất kỳ bản ghi phù hợp nào trong bảng "bên phải" ( Vị trí ). Đây là SQL cho phép nối ngoài bên trái trông như thế nào, sử dụng các bảng ở trên:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Bây giờ, đây là kết quả của việc chạy SQL này sẽ như thế nào:

Tham gia bên ngoài bên phải: - Tham gia bên ngoài bên phải (hoặc tham gia bên phải) gần giống với tham gia bên ngoài bên trái, ngoại trừ việc xử lý các bảng bị đảo ngược. Mỗi hàng từ bảng "bên phải" ( Vị trí ) sẽ xuất hiện trong bảng đã tham gia ít nhất một lần. Nếu không có hàng phù hợp từ bảng "bên trái" ( Nhân viên ), NULL sẽ xuất hiện trong các cột từ Nhân viên cho những hồ sơ không khớp trong Vị trí . Đây là những gì SQL trông giống như:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Sử dụng các bảng ở trên, chúng ta có thể hiển thị tập kết quả của phép nối ngoài bên phải sẽ như thế nào:

Tham gia ngoài đầy đủ: - Tham gia đầy đủ bên ngoài hoặc Tham gia đầy đủ là để giữ lại thông tin không khớp bằng cách bao gồm các hàng không khớp trong kết quả của liên kết, sử dụng kết nối ngoài đầy đủ. Nó bao gồm tất cả các hàng từ cả hai bảng, bất kể bảng kia có giá trị khớp hay không.
Chỉ lấy các hàng phù hợp, nghĩa là , A intersect B.

SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Chọn tất cả các bản ghi từ bảng đầu tiên và bất kỳ bản ghi nào trong bảng thứ hai khớp với các phím đã nối.

SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Chọn tất cả các bản ghi từ bảng thứ hai và bất kỳ bản ghi nào trong bảng đầu tiên khớp với các phím đã nối.

SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Nói một cách đơn giản:
Một tham gia bên trong chỉ lấy các hàng phù hợp.
Trong khi đó một phép nối ngoài lấy các hàng khớp từ một bảng và tất cả các hàng trong bảng khác .... kết quả phụ thuộc vào việc bạn đang sử dụng cái nào:
Trái : Các hàng khớp trong bảng bên phải và tất cả các hàng trong bảng bên trái
Phải : Các hàng khớp trong bảng bên trái và tất cả các hàng trong bảng bên phải hoặc
Đầy đủ : Tất cả các hàng trong tất cả các bảng. Không có vấn đề gì nếu có trận đấu hay không
Một kết nối bên trong chỉ hiển thị các hàng nếu có một bản ghi khớp ở phía bên kia (bên phải) của liên kết.
Một kết nối bên ngoài (bên trái) hiển thị các hàng cho mỗi bản ghi ở phía bên trái, ngay cả khi không có hàng phù hợp ở phía bên kia (bên phải) của liên kết. Nếu không có hàng phù hợp, các cột cho phía bên phải (bên phải) sẽ hiển thị NULL.
Các phép nối bên trong yêu cầu một bản ghi có ID liên quan tồn tại trong bảng đã nối.
Các kết nối bên ngoài sẽ trả về các bản ghi cho bên trái ngay cả khi không có gì tồn tại cho bên phải.
Chẳng hạn, bạn có một Đơn hàng và bảng OrderDetails. Chúng có liên quan bởi một "OrderID".
Đơn đặt hàng
Đặt hàng chi tiết
Yêu cầu
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
sẽ chỉ trả về các Đơn hàng cũng có thứ gì đó trong bảng OrderDetails.
Nếu bạn thay đổi nó thành OUTER LEFT THAM GIA
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
sau đó nó sẽ trả về các bản ghi từ bảng Đơn hàng ngay cả khi chúng không có bản ghi OrderDetails.
Bạn có thể sử dụng điều này để tìm các Đơn đặt hàng không có bất kỳ OrderDetails nào chỉ ra một đơn hàng mồ côi có thể bằng cách thêm một mệnh đề where như thế nào WHERE OrderDetails.OrderID IS NULL.
SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c, categories_description cd WHERE c.id = cd.categories_id AND c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASCđể SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c INNER JOIN categories_description cd ON c.id = cd.categories_id WHERE c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC(MySQL) với thành công. Tôi không chắc chắn về các điều kiện bổ sung, chúng trộn lẫn với nhau ...
Nói một cách đơn giản:
Kết nối bên trong -> CHỈ lấy các bản ghi chung từ bảng cha và con WHERE khóa chính của bảng cha khớp với khóa ngoài trong bảng con.
Còn lại tham gia ->
mã giả
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
Tham gia phải : Chính xác đối diện với tham gia trái. Đặt tên của bảng trong LEFT THAM GIA ở bên phải trong Tham gia phải, bạn nhận được đầu ra giống như TRÁI THAM GIA.
Tham gia ngoài : Hiển thị tất cả các bản ghi trong cả hai bảng No matter what. Nếu các bản ghi trong bảng Trái không khớp với bảng bên phải dựa trên khóa Chính, Khóa trước, hãy sử dụng giá trị NULL làm kết quả của phép nối.
Thí dụ :

Cho phép bây giờ cho 2 bảng
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Ở đây, bảng nhân viên là bảng Master, phone_numbers_emp NHÂN là bảng con (nó chứa emp_idkhóa ngoại kết nối employee.idvới bảng con của nó.)
Tham gia bên trong
Lấy bản ghi của 2 bảng CHỈ NẾU Khóa chính của bảng nhân viên (id của nó) khớp với khóa ngoài của bảng con phone_numbers_emp NHÂN (emp_id) .
Vì vậy, truy vấn sẽ là:
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Ở đây chỉ lấy các hàng khớp với khóa chính = khóa ngoại như đã giải thích ở trên. Ở đây, các hàng không khớp trên khóa chính = khóa ngoại được bỏ qua do tham gia.
Tham gia trái :
Tham gia bên trái giữ lại tất cả các hàng của bảng bên trái, bất kể có một hàng khớp với bảng bên phải hay không.
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Tham gia bên ngoài :
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Theo sơ đồ, nó trông giống như:

Bạn sử dụng INNER JOINđể trả về tất cả các hàng từ cả hai bảng có khớp. tức là trong bảng kết quả, tất cả các hàng và cột sẽ có giá trị.
Trong OUTER JOINbảng kết quả có thể có các cột trống. Tham gia bên ngoài có thể LEFThoặc RIGHT.
LEFT OUTER JOIN trả về tất cả các hàng từ bảng đầu tiên, ngay cả khi không có kết quả khớp trong bảng thứ hai.
RIGHT OUTER JOIN trả về tất cả các hàng từ bảng thứ hai, ngay cả khi không có kết quả khớp trong bảng đầu tiên.
Đây là một lời giải thích sơ đồ tốt cho tất cả các loại tham gia
nguồn: http://ssiddique.info/under Hiểu-sql-joins-in-easy-way.html
INNER JOINyêu cầu có ít nhất một trận đấu trong việc so sánh hai bảng. Ví dụ, bảng A và bảng B ngụ ý A ٨ B (A giao nhau B).
LEFT OUTER JOINvà LEFT JOINgiống nhau Nó cung cấp cho tất cả các bản ghi khớp trong cả hai bảng và tất cả các khả năng của bảng bên trái.
Tương tự, RIGHT OUTER JOINvà RIGHT JOINgiống nhau. Nó cung cấp cho tất cả các bản ghi khớp trong cả hai bảng và tất cả các khả năng của bảng bên phải.
FULL JOINlà sự kết hợp của LEFT OUTER JOINvà RIGHT OUTER JOINkhông có sự trùng lặp.
Câu trả lời là trong ý nghĩa của từng người, vì vậy trong kết quả.
Lưu ý:
TrongSQLiteđó không cóRIGHT OUTER JOINhoặcFULL OUTER JOIN.
Và cũngMySQLkhông cóFULL OUTER JOIN.
Câu trả lời của tôi dựa trên Lưu ý ở trên .
Khi bạn có hai bảng như thế này:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
THAM GIA CROSS / NGOÀI THAM GIA:
Bạn có thể có tất cả các dữ liệu bảng đó với CROSS JOINhoặc chỉ với ,như thế này:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
THAM GIA THAM GIA:
Khi bạn muốn thêm bộ lọc vào các kết quả trên dựa trên mối quan hệ như table1.id = table2.idbạn có thể sử dụng INNER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
TRÁI [NGOÀI] THAM GIA:
Khi bạn muốn có tất cả các hàng của một trong các bảng trong kết quả trên - với cùng một mối quan hệ - bạn có thể sử dụng LEFT JOIN:
(Đối với RIGHT THAM GIA chỉ cần thay đổi vị trí của các bảng)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
FULL OUTER THAM GIA:
Khi bạn cũng muốn có tất cả các hàng của bảng khác trong kết quả của mình, bạn có thể sử dụng FULL OUTER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
Vâng, vì nhu cầu của bạn, bạn chọn từng cái đáp ứng nhu cầu của bạn;).
full outer jointrong MySQL.
Tham gia nội tâm.
Một phép nối được kết hợp các hàng từ hai bảng. Một phép nối bên trong cố gắng khớp hai bảng dựa trên các tiêu chí bạn chỉ định trong truy vấn và chỉ trả về các hàng khớp. Nếu một hàng từ bảng đầu tiên trong phép nối khớp với hai hàng trong bảng thứ hai, thì hai hàng sẽ được trả về trong kết quả. Nếu có một hàng trong bảng đầu tiên không khớp với một hàng trong bảng thứ hai, nó sẽ không được trả về; tương tự, nếu có một hàng trong bảng thứ hai không khớp với một hàng trong bảng đầu tiên, nó sẽ không được trả về.
Tham gia ngoài.
Một liên kết bên trái cố gắng tìm khớp các hàng từ bảng đầu tiên đến các hàng trong bảng thứ hai. Nếu không thể tìm thấy kết quả khớp, nó sẽ trả về các cột từ bảng đầu tiên và để trống các cột từ bảng thứ hai (null).
INNER JOINtham gia điển hình nhất cho hai hoặc nhiều bảng. Nó trả về kết quả khớp dữ liệu trên cả hai bảng ON quan hệ khóa chính và forignkey.OUTER JOINgiống như INNER JOIN, nhưng nó cũng bao gồm NULLdữ liệu trên result Set.
LEFT JOIN= INNER JOIN+ Dữ liệu chưa từng có của bảng bên tráiNull khớp với bảng bên phải.RIGHT JOIN= INNER JOIN+ Dữ liệu chưa từng có của bảng bên phảiNull khớp với bảng bên trái.FULL JOIN= INNER JOIN+ Dữ liệu chưa từng có trên cả hai bảng bên phải và bên trái có Nullkhớp.INNER JOINvà OUTER JOINchúng ta có thể viết các truy vấn tự tham gia.Ví dụ:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
Tôi không thấy nhiều chi tiết về hiệu suất và trình tối ưu hóa trong các câu trả lời khác.
Đôi khi thật tốt khi biết rằng chỉ INNER JOINcó liên kết có nghĩa là trình tối ưu hóa có nhiều tùy chọn nhất để chơi với nó. Nó có thể sắp xếp lại thứ tự tham gia để làm cho nó nhanh hơn giữ kết quả tương tự. Trình tối ưu hóa có thể sử dụng các chế độ tham gia nhất.
Nói chung, đó là một thực hành tốt để cố gắng sử dụng INNER JOINthay vì các loại tham gia khác nhau. (Tất nhiên nếu có thể xem xét tập kết quả dự kiến.)
Có một vài ví dụ hay và giải thích ở đây về hành vi kết hợp kỳ lạ này:
INNER JOINlà chậm hơn so với LEFT JOINhầu hết mọi lúc, Và mọi người có thể sử dụng LEFT JOINthay vì INNER JOINthêm một WHEREđể xóa NULLkết quả không mong muốn ;).
INNERlà chậm hơn?
Đã chỉ trích sơ đồ Venn màu đỏ rất được yêu thích, tôi nghĩ chỉ công bằng khi đăng nỗ lực của mình.
Mặc dù câu trả lời của @Martin Smith là tốt nhất trong nhóm này, nhưng anh ta chỉ hiển thị cột khóa từ mỗi bảng, trong khi tôi nghĩ rằng các cột không khóa cũng lý tưởng cũng nên được hiển thị.
Điều tốt nhất tôi có thể làm trong nửa giờ cho phép, tôi vẫn không nghĩ rằng điều đó cho thấy đầy đủ rằng các null ở đó do không có các giá trị chính trong TableBhoặc đó OUTER JOINthực sự là một liên minh chứ không phải là tham gia:
TableA a LEFT OUTER JOIN TableB b bằngTableB B RIGHT OUTER JOIN TableA a
Các thuật toán chính xác cho INNER JOIN, LEFT/RIGHT OUTER JOINnhư sau:
a(a, b[i])ON ...mệnh đề đối với từng cặp:ON( a, b[i] ) = true/false?
true, trả về hàng kết hợp đó (a, b[i]).Outer Join cặp (ảo) sau đó sử dụng Nullcho tất cả các cột của bảng khác: (a, Null)cho phép nối ngoài LEFT hoặc (Null, b)cho phép nối ngoài RIGHT. Điều này là để đảm bảo tất cả các hàng của bảng đầu tiên tồn tại trong kết quả cuối cùng.Lưu ý: điều kiện được chỉ định trong ONmệnh đề có thể là bất cứ điều gì, không bắt buộc phải sử dụng Khóa chính (và bạn không cần phải luôn luôn tham khảo Cột từ cả hai bảng)! Ví dụ:
... ON T1.title = T2.title AND T1.version < T2.version(=> xem bài đăng này dưới dạng sử dụng mẫu: Chỉ chọn các hàng có giá trị tối đa trên một cột )... ON T1.y IS NULL... ON 1 = 0 (giống như mẫu)Ghi chú: Tham gia trái = Tham gia ngoài trái, Tham gia phải = Tham gia ngoài phải.
Định nghĩa đơn giản nhất
Tham gia bên trong: Trả về các bản ghi khớp từ cả hai bảng.
Tham gia đầy đủ bên ngoài: Trả về các bản ghi khớp và chưa từng có từ cả hai bảng bằng null cho các bản ghi chưa từng có từ cả hai bảng .
Left Outer Join: Trả về các bản ghi khớp và chưa từng có chỉ từ bảng bên trái .
Right Outer Join: Trả về các bản ghi khớp và chưa từng có từ bảng bên phải .
Nói ngắn gọn
Phù hợp + Trái chưa từng có + Phải chưa từng có = Tham gia ngoài đầy đủ
Phù hợp + Trái chưa từng có = Tham gia ngoài trái
Phù hợp + Phải chưa từng có = Tham gia bên ngoài phải
Phù hợp = Tham gia nội bộ
Trong điều khoản đơn giản,
1. THAM GIA THAM GIA HOẶC THIẾT BỊ THAM GIA: Trả về tập kết quả chỉ khớp với điều kiện trong cả hai bảng.
2. OUTER THAM GIA: Trả về tập kết quả của tất cả các giá trị từ cả hai bảng ngay cả khi có điều kiện khớp hay không.
3. TRÁI PHIẾU: Trả về tập kết quả của tất cả các giá trị từ bảng bên trái và chỉ các hàng khớp với điều kiện trong bảng bên phải.
4. RIGHT THAM GIA: Trả về tập kết quả của tất cả các giá trị từ bảng bên phải và chỉ các hàng khớp với điều kiện trong bảng bên trái.
5. FULL THAM GIA: Tham gia đầy đủ và Tham gia đầy đủ bên ngoài là như nhau.
Ví dụ
Giả sử bạn có hai bảng, mỗi cột có một cột và dữ liệu như sau:
A B
- -
1 3
2 4
3 5
4 6
7
8
Lưu ý rằng (1,2,7,8) là duy nhất đối với A, (3,4) là phổ biến và (5,6) là duy nhất đối với B.
Từ khóa INNER THAM GIA chọn tất cả các hàng từ cả hai bảng miễn là điều kiện thỏa mãn. Từ khóa này sẽ tạo tập kết quả bằng cách kết hợp tất cả các hàng từ cả hai bảng trong đó điều kiện thỏa mãn tức là giá trị của trường chung sẽ giống nhau.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
Kết quả:
a | b
--+--
3 | 3
4 | 4
Phép nối này trả về tất cả các hàng của bảng ở phía bên trái của phép nối và các hàng khớp với bảng ở phía bên phải của phép nối. Các hàng không có hàng khớp ở bên phải, tập kết quả sẽ chứa null. THAM GIA TRÁI CÂY còn được gọi là LEFT OUTER JOIN.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
Kết quả:
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
7 | null
8 | null
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
Kết quả:
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
ĐẦY ĐỦ (NGOÀI) THAM GIA :
FULL THAM GIA tạo ra tập kết quả bằng cách kết hợp kết quả của cả LEFT THAM GIA và RIGHT THAM GIA. Tập kết quả sẽ chứa tất cả các hàng từ cả hai bảng. Các hàng không khớp, tập kết quả sẽ chứa các giá trị NULL.
select * from a FULL OUTER JOIN b on a.a = b.b;
Kết quả:
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
7 | null
8 | null
Liên kết bên trong - Một kết nối bên trong bằng cách sử dụng một trong hai truy vấn tương đương sẽ cho giao điểm của hai bảng , tức là hai hàng chúng có chung.
Nối ngoài trái - Một nối ngoài ngoài trái sẽ cho tất cả các hàng trong A, cộng với bất kỳ hàng phổ biến nào trong B.
Tham gia ngoài đầy đủ - Tham gia ngoài đầy đủ sẽ cung cấp cho bạn kết hợp của A và B, tức là Tất cả các hàng trong A và tất cả các hàng trong B. Nếu một cái gì đó trong A không có mốc chuẩn tương ứng trong B, thì phần B là không, và ngược lại
Join is not an intersection unless the tables have the same columns. Bạn có thể tham gia bất kỳ cột nào bạn muốn và nếu giá trị khớp, chúng sẽ tham gia cùng nhau.
1. Tham gia bên trong: Còn được gọi là Tham gia. Nó trả về các hàng có trong cả bảng bên trái và bảng bên phải chỉ khi có khớp . Nếu không, nó trả về không có hồ sơ.
Thí dụ:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2. Tham gia đầy đủ bên ngoài: Còn được gọi là Tham gia đầy đủ. Nó trả về tất cả các hàng có trong cả bảng bên trái và bảng bên phải.
Thí dụ:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3. Tham gia bên ngoài bên trái: Hoặc đơn giản được gọi là Tham gia bên trái. Nó trả về tất cả các hàng có trong bảng bên trái và các hàng khớp từ bảng bên phải (nếu có).
4. Tham gia bên ngoài bên phải: Còn được gọi là Tham gia đúng. Nó trả về các hàng khớp từ bảng bên trái (nếu có) và tất cả các hàng có trong bảng bên phải.
Ưu điểm của Joins
Xem xét dưới 2 bảng:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
Phòng ban
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
Chủ yếu được viết là chỉ THAM GIA trong các truy vấn sql. Nó chỉ trả về các bản ghi khớp giữa các bảng.
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
Như bạn thấy ở trên, Josekhông được in từ EMP trong đầu ra vì dept_id 6không tìm thấy kết quả khớp trong bảng Cục. Tương tự, HRvà R&Dcác hàng không được in từ bảng Cục vì chúng không tìm thấy kết quả khớp trong bảng Emp.
Vì vậy, INNER THAM GIA hoặc chỉ THAM GIA, chỉ trả về các hàng khớp.
Điều này trả về tất cả các bản ghi từ bảng TRÁI và chỉ khớp các bản ghi từ bảng ĐÚNG.
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
Vì vậy, nếu bạn quan sát đầu ra ở trên, tất cả các bản ghi từ bảng TRÁI (Emp) được in chỉ với các bản ghi khớp từ bảng PHẢI.
HRvà R&Dcác hàng không được in từ bảng Cục vì chúng không tìm thấy kết quả khớp trong bảng Emp trên dept_id.
Vì vậy, LEFT THAM GIA trả về TẤT CẢ các hàng từ bảng bên trái và chỉ khớp các hàng từ bảng PHẢI.
Cũng có thể kiểm tra DEMO tại đây .
Xin vui lòng xem câu trả lời của Martin Smith để có minh họa và giải thích tốt hơn về các liên kết khác nhau, bao gồm và đặc biệt là sự khác biệt giữa FULL OUTER JOIN, RIGHT OUTER JOINvà LEFT OUTER JOIN.
Hai bảng này tạo thành một cơ sở để biểu diễn các JOINs dưới đây:


SELECT *
FROM citizen
CROSS JOIN postalcode
Kết quả sẽ là các sản phẩm của Cartesian của tất cả các kết hợp. Không JOINcần điều kiện:

INNER JOIN cũng giống như đơn giản: JOIN

SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
Kết quả sẽ là các kết hợp thỏa mãn JOINđiều kiện cần thiết :

LEFT OUTER JOIN giống như LEFT JOIN

SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
Kết quả sẽ là tất cả mọi thứ citizenngay cả khi không có trận đấu nào postalcode. Một lần nữa một JOINđiều kiện được yêu cầu:

Tất cả các ví dụ đã được chạy trên Oracle 18c. Chúng có sẵn tại dbfiddle.uk , cũng là nơi ảnh chụp màn hình của các bảng.
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
JOINvàWHERECROSS JOINdẫn đến các hàng là Ý tưởng chung / INNER JOIN:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
Sử dụng CROSS JOINđể có được kết quả của một LEFT OUTER JOINyêu cầu thủ thuật như thêm vào một NULLhàng. Nó bị bỏ qua.
INNER JOINtrở thành một sản phẩm cartesian. Nó giống như Ý tưởng chung / CROSS JOIN:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
Đây là nơi tham gia bên trong thực sự có thể được xem là liên kết chéo với kết quả không phù hợp với điều kiện bị xóa. Ở đây không có hàng kết quả được loại bỏ.
Sử dụng INNER JOINđể có được kết quả của một LEFT OUTER JOINcũng đòi hỏi thủ thuật. Nó bị bỏ qua.
LEFT JOINkết quả trong các hàng là Ý tưởng chung / CROSS JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOINkết quả trong các hàng là Ý tưởng chung / INNER JOIN:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
Một tìm kiếm trên internet hình ảnh trên "sql tham gia chéo bên trong bên ngoài" sẽ hiển thị vô số biểu đồ Venn. Tôi đã từng có một bản in của một trên bàn của tôi. Nhưng có vấn đề với đại diện.
Biểu đồ Venn là tuyệt vời cho lý thuyết tập hợp, trong đó một phần tử có thể nằm trong một hoặc cả hai tập hợp. Nhưng đối với cơ sở dữ liệu, đối với tôi, một phần tử trong một "tập hợp" dường như là một hàng trong một bảng và do đó cũng không xuất hiện trong bất kỳ bảng nào khác. Không có thứ gọi là một hàng trong nhiều bảng. Một hàng là duy nhất cho bảng.
Tự tham gia là một trường hợp góc trong đó mỗi phần tử trên thực tế là giống nhau trong cả hai bộ. Nhưng nó vẫn không có bất kỳ vấn đề nào dưới đây.
Tập hợp Ađại diện cho tập hợp bên trái ( citizenbảng) và tập hợp Blà tập hợp bên phải ( postalcodebảng) trong cuộc thảo luận dưới đây.
Mọi yếu tố trong cả hai bộ được khớp với mọi yếu tố trong bộ khác, có nghĩa là chúng ta cần Asố lượng của mọi Byếu tố và Bsố lượng của mọi Ayếu tố để thể hiện đúng sản phẩm Cartesian này. Lý thuyết tập hợp không được tạo cho nhiều phần tử giống hệt nhau trong một tập hợp, vì vậy tôi thấy các sơ đồ Venn để thể hiện chính xác nó không thực tế / không thể. Dường như không UNIONphù hợp chút nào.
Các hàng là khác biệt. Tổng cộng UNIONcó 7 hàng. Nhưng chúng không tương thích với một SQLtập kết quả chung . Và đây không phải là cách một CROSS JOINcông trình hoàn toàn:

Cố gắng thể hiện nó như thế này:

..nhưng bây giờ nó trông giống như một cái INTERSECTION, nhưng chắc chắn là không . Hơn nữa, không có yếu tố INTERSECTIONnào thực sự nằm trong bất kỳ hai bộ riêng biệt nào. Tuy nhiên, nó trông rất giống các kết quả có thể tìm kiếm tương tự như sau:

Để tham khảo một kết quả có thể tìm kiếm cho CROSS JOINs có thể được nhìn thấy tại Tutorialgateway . Cái INTERSECTION, giống như cái này, trống rỗng.
Giá trị của một yếu tố phụ thuộc vào JOINđiều kiện. Có thể biểu diễn điều này trong điều kiện mỗi hàng trở nên duy nhất cho điều kiện đó. Ý nghĩa id=xchỉ đúng với một hàng. Khi một hàng trong bảng A( citizen) khớp với nhiều hàng trong bảng B( postalcode) theo JOINđiều kiện, kết quả có cùng các vấn đề như CROSS JOIN: Hàng cần được biểu diễn nhiều lần và lý thuyết tập hợp không thực sự được thực hiện cho điều đó. Trong điều kiện duy nhất, sơ đồ có thể hoạt động, nhưng hãy nhớ rằng JOINđiều kiện xác định vị trí của một phần tử trong sơ đồ. Chỉ nhìn vào các giá trị của JOINđiều kiện với phần còn lại của hàng chỉ để đi xe:

Đại diện này hoàn toàn tách rời khi sử dụng INNER JOINmột ON 1 = 1điều kiện làm cho nó thành một CROSS JOIN.
Với bản thân JOIN, các hàng trong thực tế là các phần tử lý tưởng trong cả hai bảng, nhưng đại diện cho các bảng là cả hai Avà Bkhông phù hợp lắm. Ví dụ một tự chung JOINđiều kiện mà làm cho một phần tử trong Ađể thể đang khớp khác nhau phần tử trong B ON A.parent = B.child, làm cho trận đấu từ Ađể Bvào các yếu tố riêng biệt. Từ các ví dụ sẽ là SQLnhư thế này:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader

Nghĩa là Smith là thủ lĩnh của cả Green và Jensen.
Một lần nữa, rắc rối bắt đầu khi một hàng có nhiều kết quả khớp với các hàng trong bảng khác. Điều này còn phức tạp hơn vì OUTER JOINcó thể mặc dù phù hợp với tập hợp trống. Nhưng trong lý thuyết tập hợp, sự kết hợp của bất kỳ tập hợp nào Cvà một tập hợp trống, luôn luôn là như vậy C. Bộ trống không thêm gì. Đại diện của điều này LEFT OUTER JOINthường chỉ hiển thị tất cả Ađể minh họa rằng các hàng trong Ađược chọn bất kể có khớp hay không B. Tuy nhiên, "các yếu tố phù hợp" có cùng các vấn đề như minh họa ở trên. Họ phụ thuộc vào điều kiện. Và bộ trống dường như đã lang thang đến A:

Tìm tất cả các hàng từ a CROSS JOINvới Smith và mã bưu chính trên Mặt trăng:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';

Bây giờ biểu đồ Venn không được sử dụng để phản ánh JOIN. Nó chỉ được sử dụng cho WHEREmệnh đề:

.. và điều đó có ý nghĩa.
Như đã giải thích một INNER JOINkhông thực sự là một INTERSECT. Tuy nhiên INTERSECTs có thể được sử dụng trên các kết quả của các truy vấn riêng biệt. Ở đây một sơ đồ Venn có ý nghĩa, bởi vì các yếu tố từ các truy vấn riêng biệt trên thực tế là các hàng thuộc về một trong hai kết quả hoặc cả hai. Intersect rõ ràng sẽ chỉ trả về kết quả trong đó hàng có mặt trong cả hai truy vấn. Điều này SQLsẽ dẫn đến cùng một hàng như trên WHEREvà biểu đồ Venn cũng sẽ giống nhau:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
An OUTER JOINkhông phải là a UNION. Tuy nhiên, UNIONlàm việc trong cùng điều kiện như INTERSECT, dẫn đến trả về tất cả các kết quả kết hợp cả hai SELECT:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
tương đương với:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
..và đưa ra kết quả:

Cũng ở đây một sơ đồ Venn có ý nghĩa:

Một lưu ý quan trọng là chúng chỉ hoạt động khi cấu trúc của các kết quả từ hai CHỌN giống nhau, cho phép so sánh hoặc kết hợp. Kết quả của hai điều này sẽ không cho phép:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
..trying để kết hợp các kết quả với UNIONcung cấp cho một
ORA-01790: expression must have same datatype as corresponding expression
Để biết thêm sự quan tâm, hãy đọc Nói KHÔNG với Biểu đồ Venn khi Giải thích THAM GIA và sql tham gia dưới dạng biểu đồ venn . Cả hai cũng che chở EXCEPT.
Có rất nhiều câu trả lời hay ở đây với các ví dụ đại số quan hệ rất chính xác . Dưới đây là một câu trả lời rất đơn giản có thể hữu ích cho các lập trình viên nghiệp dư hoặc người mới với các tình huống khó xử về mã hóa SQL.
Về cơ bản, thường xuyên hơn không, các truy vấn JOINcó hai trường hợp:
Đối với SELECTtập hợp con của dữ liệu A:
INNER JOINkhi dữ liệu liên quan Bbạn đang tìm kiếm PHẢI tồn tại trên mỗi thiết kế cơ sở dữ liệu;LEFT JOINkhi dữ liệu liên quan Bbạn đang tìm kiếm MIGHT hoặc MIGHT KHÔNG tồn tại trên mỗi thiết kế cơ sở dữ liệu.Sự khác biệt giữa inner joinvà outer joinnhư sau:
Inner join là một phép nối kết hợp các bảng dựa trên các bộ dữ liệu phù hợp, trong khi outer join là một phép nối mà bảng kết hợp dựa trên cả bộ dữ liệu khớp và không khớp.Inner join hợp nhất hàng khớp từ hai bảng trong đó hàng không khớp được bỏ qua, trong khi outer join hợp nhất các hàng từ hai bảng và hàng không với giá trị null.Inner join giống như một hoạt động giao nhau, trong khi outer join giống như một hoạt động công đoàn.Inner join là hai loại, trong khi outer join là ba loại.outer joinnhanh hơn inner join.