Sự khác biệt giữa INNER JOIN và LEFT SEMI JOIN


82

Sự khác biệt giữa một INNER JOINvà là LEFT SEMI JOINgì?

Trong tình huống dưới đây, tại sao tôi nhận được hai kết quả khác nhau?

Tập INNER JOINkết quả lớn hơn rất nhiều. Ai đó có thể giải thích? Tôi đang cố gắng đưa những cái tên trong table_1đó chỉ xuất hiện trong table_2.

SELECT name
FROM table_1 a
    INNER JOIN table_2 b ON a.name=b.name

SELECT name
FROM table_1 a
    LEFT SEMI JOIN table_2 b ON (a.name=b.name)

2
Sự tham gia bên trong sẽ đạt được mục tiêu của bạn. Tôi chưa bao giờ nghe nói về bán tham gia cho đến khi tôi thấy câu hỏi này.
Dan Bracuk

Các left semi joinNên trở về hàng nhiều hơn inner join.
Gordon Linoff

1
Các inner joinsẽ trả lại dữ liệu chỉ khi có một trận đấu giữa hai bảng. Các left joinsẽ trả lại dữ liệu từ bảng đầu tiên không phân biệt nếu một bản ghi tương ứng được tìm thấy trong bảng thứ hai.
j03z

11
@GordonLinoff không nhất thiết, a LEFT SEMI JOINsẽ chỉ trả về một hàng từ bên trái, ngay cả khi có nhiều kết quả phù hợp ở bên phải. An INNER JOINsẽ trả về nhiều hàng nếu có nhiều kết hợp ở bên phải.
D Stanley

1
@ j03z không thể đúng. Nếu mục đích của phép nối hemi bên trái là 1) để chỉ trả lại thông tin trong bảng bên trái (như những người khác đã nói) và 2) để trả lại các hàng từ bảng bên trái bất kể khớp (như tôi nghĩ bạn nói) thì đó là chỉ là bảng bên trái ban đầu - không cần nối để thực hiện điều đó. Tôi nghĩ những người khác phải chính xác rằng liên kết hemi bên trái 1) chỉ trả về các cột từ bảng bên trái, 2) chỉ trả về các hàng có kết quả phù hợp trong bảng bên phải và 3) sẽ trả về một hàng duy nhất từ ​​bên trái cho một hoặc nhiều trận đấu hơn.
Carl G

Câu trả lời:


120

An INNER JOINcó thể trả về dữ liệu từ các cột từ cả hai bảng và có thể sao chép các giá trị của bản ghi ở hai bên có nhiều hơn một đối sánh. A LEFT SEMI JOINchỉ có thể trả về các cột từ bảng bên trái và mang lại một trong mỗi bản ghi từ bảng bên trái nơi có một hoặc nhiều kết quả phù hợp trong bảng bên phải (bất kể số lượng trận đấu). Nó tương đương với (trong SQL chuẩn):

SELECT name
FROM table_1 a
WHERE EXISTS(
    SELECT * FROM table_2 b WHERE (a.name=b.name))

Nếu có nhiều hàng phù hợp trong cột bên phải, an INNER JOINsẽ trả về một hàng cho mỗi kết quả khớp trên bảng bên phải, trong khi a LEFT SEMI JOINchỉ trả về các hàng từ bảng bên trái, bất kể số hàng phù hợp ở phía bên phải. Đó là lý do tại sao bạn thấy một số hàng khác nhau trong kết quả của mình.

Tôi đang cố lấy các tên trong bảng_1 chỉ xuất hiện trong bảng_2.

Sau đó, a LEFT SEMI JOINlà truy vấn thích hợp để sử dụng.


Có thực sự là một điều như một LEFT SEMI JOIN? Không chỉ là một SEMI JOIN? Không có ý nghĩa gì đối với a RIGHT SEMI JOIN, phải không?
ErikE

Trong Hive , có.
D Stanley,

1
câu trả lời tuyệt vời đúng với những gì tôi đang tìm kiếm. i sẽ cụm từ câu trả lời chính xác hơn:" ... một INNER JOIN sẽ trở lại một hàng cho mỗi khớp hàng của bảng bên phải , trong khi một LEFT BÁN THAM GIA ...
Barak1731475

2
Ngược lại với điều này là LEFT ANTI JOIN sẽ lọc ra dữ liệu từ bảng bên phải trong bảng bên trái theo một khóa. Tôi đã nghĩ rằng tôi sẽ để lại món đồ này ở đây cho ai đó có thể đang tìm kiếm!
shantanusinghal

63

Giả sử có 2 bảng TableA và TableB chỉ có 2 cột (Id, Data) và dữ liệu sau:

BảngA:

+----+---------+
| Id |  Data   |
+----+---------+
|  1 | DataA11 |
|  1 | DataA12 |
|  1 | DataA13 |
|  2 | DataA21 |
|  3 | DataA31 |
+----+---------+

BảngB:

+----+---------+
| Id |  Data   |
+----+---------+
|  1 | DataB11 |
|  2 | DataB21 |
|  2 | DataB22 |
|  2 | DataB23 |
|  4 | DataB41 |
+----+---------+

Tham gia bên trong trên cột Idsẽ trả về các cột từ cả hai bảng và chỉ các bản ghi phù hợp:

.----.---------.----.---------.
| Id |  Data   | Id |  Data   |
:----+---------+----+---------:
|  1 | DataA11 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA12 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA13 |  1 | DataB11 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB21 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB22 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB23 |
'----'---------'----'---------'

Kết nối Trái (hoặc Kết nối bên ngoài bên trái) trên cột Idsẽ trả về các cột từ cả bảng và các bản ghi khớp với bản ghi từ bảng bên trái (Giá trị rỗng từ bảng bên phải):

.----.---------.----.---------.
| Id |  Data   | Id |  Data   |
:----+---------+----+---------:
|  1 | DataA11 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA12 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA13 |  1 | DataB11 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB21 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB22 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB23 |
:----+---------+----+---------:
|  3 | DataA31 |    |         |
'----'---------'----'---------'

Tham gia bên phải (hoặc tham gia bên ngoài bên phải) trên cột Idsẽ trả về các cột từ cả bảng và các bản ghi khớp với bản ghi từ bảng bên phải (Giá trị rỗng từ bảng bên trái):

┌────┬─────────┬────┬─────────┐
│ Id │  Data   │ Id │  Data   │
├────┼─────────┼────┼─────────┤
│  1 │ DataA11 │  1 │ DataB11 │
│  1 │ DataA12 │  1 │ DataB11 │
│  1 │ DataA13 │  1 │ DataB11 │
│  2 │ DataA21 │  2 │ DataB21 │
│  2 │ DataA21 │  2 │ DataB22 │
│  2 │ DataA21 │  2 │ DataB23 │
│    │         │  4 │ DataB41 │
└────┴─────────┴────┴─────────┘

Full Outer Join trên cột Idsẽ trả về các cột từ cả bảng và khớp các bản ghi với các bản ghi từ bảng bên trái (Giá trị rỗng từ bảng bên phải) và các bản ghi từ bảng bên phải (Giá trị rỗng từ bảng bên trái):

╔════╦═════════╦════╦═════════╗
║ Id ║  Data   ║ Id ║  Data   ║
╠════╬═════════╬════╬═════════╣
║  - ║         ║    ║         ║
║  1 ║ DataA11 ║  1 ║ DataB11 ║
║  1 ║ DataA12 ║  1 ║ DataB11 ║
║  1 ║ DataA13 ║  1 ║ DataB11 ║
║  2 ║ DataA21 ║  2 ║ DataB21 ║
║  2 ║ DataA21 ║  2 ║ DataB22 ║
║  2 ║ DataA21 ║  2 ║ DataB23 ║
║  3 ║ DataA31 ║    ║         ║
║    ║         ║  4 ║ DataB41 ║
╚════╩═════════╩════╩═════════╝

Left Semi Join trên cột Idsẽ chỉ trả về các cột từ bảng bên trái và chỉ khớp các bản ghi từ bảng bên trái:

┌────┬─────────┐
│ Id │  Data   │
├────┼─────────┤
│  1 │ DataA11 │
│  1 │ DataA12 │
│  1 │ DataA13 │
│  2 │ DataA21 │
└────┴─────────┘

Tôi từng gọi đây là "Tham gia BÊN TRONG TRÁI".
Anshul Joshi,

DISTINCT của A. * từ kết quả INNER JOIN tương đương với LEFT SEMI JOIN.
Teja

4
Phân biệt có vẻ không an toàn, giả sử A chứa hai bản ghi giống nhau.
Dennis Jaheruddin

Ngay cả khi kết quả cuối cùng giống nhau, sử dụng DISTINCT có thể có gói đắt hơn so với EXISTS
manotheshark

32

Đã thử trong Hive và nhận được kết quả dưới đây

Bảng 1

1, wqe, chennai, ấn độ

2, stu, salem, ấn độ

3, mia, bangalore, ấn độ

4, yepie, newyork, Hoa Kỳ

ban 2

1, wqe, chennai, ấn độ

2, stu, salem, ấn độ

3, mia, bangalore, ấn độ

5, chapie, Los angel, USA

Tham gia bên trong

SELECT * FROM table1 INNER JOIN table2 ON (table1.id = table2.id);

1 wqe chennai Ấn Độ 1 wqe chennai Ấn Độ

2 stu salem Ấn Độ 2 stu salem Ấn Độ

3 mia bangalore Ấn Độ 3 mia bangalore Ấn Độ

Chỗ nối bên trái

SELECT * FROM table1 LEFT JOIN table2 ON (table1.id = table2.id);

1 wqe chennai Ấn Độ 1 wqe chennai Ấn Độ

2 stu salem Ấn Độ 2 stu salem Ấn Độ

3 mia bangalore Ấn Độ 3 mia bangalore Ấn Độ

4 yepie newyork USA NULL NULL NULL NULL

Tham gia bán bên trái

SELECT * FROM table1 LEFT SEMI JOIN table2 ON (table1.id = table2.id);

1 wqe chennai Ấn Độ

2 stu salem Ấn Độ

3 mia bangalore Ấn Độ

lưu ý: Chỉ các bản ghi trong bảng bên trái được hiển thị trong khi kết hợp bên trái cả hai bản ghi bảng được hiển thị

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.