内联接和左半联接之间的区别


82

INNER JOIN和之间有什么区别LEFT SEMI JOIN

在以下情况下,为什么我会得到两个不同的结果?

INNER JOIN结果集是很多大。有人可以解释吗?我试图让其中的名称table_1仅出现在中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
内部联接将实现您的目标。在看到这个问题之前,我从未听说过半加入。
Dan Bracuk 2014年

left semi join返回行应比的多inner join
Gordon Linoff 2014年

1
inner join仅当有两个表之间的匹配将返回数据。left join无论第二张表中是否找到匹配记录,都会从第一张表中返回数据。
j03z 2014年

11
@GordonLinoff不一定,LEFT SEMI JOIN即使右侧有多个匹配项,a也只会从左侧返回一行。INNER JOIN如果右侧有多个匹配项,则An将返回多行。
D Stanley

1
@ j03z可能不正确。如果左半联接的目的是1)仅返回左表中的信息(如其他人所说的)和2)返回左表中的行,而不考虑匹配(如我想的那样),那么这就是只是原始的左表-无需连接即可完成此操作。我认为其他人一定是正确的,左半连接1)仅返回左表中的列,2)仅返回右表中具有匹配项的行,3)将从左表中返回一行,或者更多比赛。
卡尔·G

Answers:


120

AnINNER JOIN可以从两个表的列中返回数据,并且可以在任一侧重复记录的值具有多个匹配项。一种LEFT SEMI JOIN只能从左侧表返回列,并从左侧表中产生每个记录之一,其中右侧表中有一个或多个匹配项(与匹配数无关)。等效于(在标准SQL中):

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

如果右侧列中有多个匹配行,则INNER JOIN在右侧表上的每个匹配项都会返回一行,而LEFT SEMI JOIN无论右侧的匹配行数是多少,a只会返回左侧表中的行。这就是为什么您在结果中看到不同数量的行的原因。

我正在尝试获取仅出现在表_2中的表_1中的名称。

然后aLEFT SEMI JOIN是要使用的适当查询。


真的有这样的事情LEFT SEMI JOIN吗?不只是一个SEMI JOIN吗?对a没有意义,对RIGHT SEMI JOIN吗?
ErikE

Hive中,是的。
D Stanley

1
很好的答案,正是我想要的。我会更准确地表达答案:“ ... INNER JOIN将为右表的每个匹配返回一行,而LEFT SEMI JOIN ...
Barak1731475 2015年

2
与此相反的是,LEFT ANTI JOIN根据一个键从左表的右表中筛选出数据。以为我会把这个掘金留给可能正在寻找的人!
shantanusinghal

63

假设有两个表TableA和TableB,其中只有2列(Id,Data)和以下数据:

表A:

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

表B:

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

内连接的列Id将同时返回表和匹配记录中的列:

.----.---------.----.---------.
| 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 |
'----'---------'----'---------'

列上的左连接(或左外连接)Id将同时返回表中的列以及具有左表中记录的匹配记录(右表中的Null值):

.----.---------.----.---------.
| 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 |    |         |
'----'---------'----'---------'

列上的右连接(或右外连接)Id将同时返回表中的列以及具有右表中记录的匹配记录(左表中的Null值):

┌────┬─────────┬────┬─────────┐
│ 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 │
└────┴─────────┴────┴─────────┘

“完全外部联接上”列Id将同时返回表中的列和匹配的记录,其中左表中的记录(右表中的Null值)和右表中的记录(左表中的Null值):

╔════╦═════════╦════╦═════════╗
║ 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 ║
╚════╩═════════╩════╩═════════╝

在列上的左半连接Id将仅从左表返回列,而仅从左表返回匹配记录:

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

我曾经称其为“ LEFT INNER Join”。
安舒尔·乔希

与INNER JOIN结果相差A. *等于LEFT SEMI JOIN。
Teja

4
区别听起来不安全,假设A包含两个相同的记录。
丹尼斯·贾赫鲁丁

即使结果最终是相同的,使用DISTINCT相比使用EXISTS可能会有更昂贵的计划
manotheshark

32

在Hive中尝试过并获得以下输出

表格1

印度钦奈1号

2,印度,塞勒姆

3,mia,印度班加罗尔

4,美国纽约

表2

印度钦奈1号

2,印度,塞勒姆

3,mia,印度班加罗尔

5,chapie,美国洛杉矶

内部联接

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

1 wqe金奈印度1 wqe金奈印度

2斯图塞勒姆印度2斯图塞勒姆印度

3 mia bangalore印度3 mia bangalore印度

左加入

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

1 wqe金奈印度1 wqe金奈印度

2斯图塞勒姆印度2斯图塞勒姆印度

3 mia bangalore印度3 mia bangalore印度

4 yepie newyork美国NULL NULL NULL NULL

左半连接

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

1 WQE钦奈印度

2 Stu Salem印度

3 MIA班加罗尔印度

注意:仅显示左表中的记录,而对于“左联接”显示的两个表记录

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.