web-dev-qa-db-ja.com

内部結合と左半結合の違い

INNER JOINLEFT SEMI JOINの違いは何ですか?

以下のシナリオでは、なぜ2つの異なる結果が得られますか?

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)
64
user3023355

INNER 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は一致する列ごとに1行を返しますが、LEFT SEMI JOINは左側のテーブルの行のみを返します。そのため、結果に異なる行数が表示されます。

Table_2にのみ表示されるtable_1内の名前を取得しようとしています。

その場合、LEFT SEMI JOINは使用する適切なクエリです。

95
D Stanley

2つの列(Id、Data)と次のデータのみを持つ2つのテーブルTableAとTableBがあるとします。

TableA:

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

TableB:

+----+---------+
| 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 ║
╚════╩═════════╩════╩═════════╝

Left Semi JoinIdで、左側のテーブルからのみ列を返し、左側のテーブルからのみ一致するレコードを返します。

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

Hiveで試し、以下の出力を得ました

表1

1、wqe、チェンナイ、インド

2、stu、salem、インド

3、ミア、バンガロール、インド

4、yepie、newyork、USA

テーブル2

1、wqe、チェンナイ、インド

2、stu、salem、インド

3、ミア、バンガロール、インド

5、chapie、Los angels、USA

内部結合

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

1 wqeチェンナイインド1 wqeチェンナイインド

2ステューセーラムインド2ステューセーラムインド

3 MIAバンガロールインド3 MIAバンガロールインド

左結合

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

1 wqeチェンナイインド1 wqeチェンナイインド

2ステューセーラムインド2ステューセーラムインド

3 MIAバンガロールインド3 MIAバンガロールインド

4 yepie newyork USA NULL NULL NULL NULL

左半結合

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

1 WQEチェンナイインド

2 Stu Salemインド

3 MIAバンガロールインド

注:左のテーブルのレコードのみが表示されますが、左結合の場合は両方のテーブルレコードが表示されます

30
Kumar