Ngoài ra làm thế nào LEFT JOIN
, RIGHT JOIN
và FULL JOIN
phù hợp với?
Ngoài ra làm thế nào LEFT JOIN
, RIGHT JOIN
và FULL JOIN
phù 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.
on
mệ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 ON
mệ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 NULL
cá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 NULL
thử nghiệm không thể rỗng hoặc điều kiện nối đảm bảo rằng mọi NULL
giá 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ó NULL
giá 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=0
vị 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 ALL
trong hai bảng.
Lưu ý rằng WHERE
mệ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_id
khóa ngoại kết nối employee.id
vớ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 JOIN
bảng kết quả có thể có các cột trống. Tham gia bên ngoài có thể LEFT
hoặ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 JOIN
yê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 JOIN
và LEFT JOIN
giố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 JOIN
và RIGHT JOIN
giố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 JOIN
là sự kết hợp của LEFT OUTER JOIN
và RIGHT OUTER JOIN
khô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 JOIN
hoặcFULL OUTER JOIN
.
Và cũngMySQL
khô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 JOIN
hoặ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.id
bạ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 join
trong 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 JOIN
tham 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 JOIN
giống như INNER JOIN
, nhưng nó cũng bao gồm NULL
dữ 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ó Null
khớp.INNER JOIN
và OUTER JOIN
chú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 JOIN
có 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 JOIN
thay 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 JOIN
là chậm hơn so với LEFT JOIN
hầu hết mọi lúc, Và mọi người có thể sử dụng LEFT JOIN
thay vì INNER JOIN
thêm một WHERE
để xóa NULL
kết quả không mong muốn ;).
INNER
là 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 TableB
hoặc đó OUTER JOIN
thự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 JOIN
như 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 Null
cho 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 ON
mệ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, Jose
không được in từ EMP trong đầu ra vì dept_id 6
không tìm thấy kết quả khớp trong bảng Cục. Tương tự, HR
và R&D
cá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.
HR
và R&D
cá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 JOIN
và LEFT OUTER JOIN
.
Hai bảng này tạo thành một cơ sở để biểu diễn các JOIN
s 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 JOIN
cầ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ứ citizen
ngay 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;
JOIN
vàWHERE
CROSS JOIN
dẫ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 JOIN
yêu cầu thủ thuật như thêm vào một NULL
hàng. Nó bị bỏ qua.
INNER JOIN
trở 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 JOIN
cũng đòi hỏi thủ thuật. Nó bị bỏ qua.
LEFT JOIN
kế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 JOIN
kế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 ( citizen
bảng) và tập hợp B
là tập hợp bên phải ( postalcode
bả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 A
số lượng của mọi B
yếu tố và B
số lượng của mọi A
yế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 UNION
phù hợp chút nào.
Các hàng là khác biệt. Tổng cộng UNION
có 7 hàng. Nhưng chúng không tương thích với một SQL
tập kết quả chung . Và đây không phải là cách một CROSS JOIN
cô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ố INTERSECTION
nà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 JOIN
s 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=x
chỉ đú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 JOIN
mộ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 A
và B
khô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
để B
vào các yếu tố riêng biệt. Từ các ví dụ sẽ là SQL
như 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 JOIN
có 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 C
và 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 JOIN
thườ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 JOIN
vớ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 WHERE
mệnh đề:
.. và điều đó có ý nghĩa.
Như đã giải thích một INNER JOIN
không thực sự là một INTERSECT
. Tuy nhiên INTERSECT
s 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 SQL
sẽ dẫn đến cùng một hàng như trên WHERE
và 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 JOIN
không phải là a UNION
. Tuy nhiên, UNION
là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 UNION
cung 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 JOIN
có hai trường hợp:
Đối với SELECT
tập hợp con của dữ liệu A
:
INNER JOIN
khi dữ liệu liên quan B
bạ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 JOIN
khi dữ liệu liên quan B
bạ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 join
và outer join
như 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 join
nhanh hơn inner join
.