また、どのようLEFT JOIN
に、RIGHT JOIN
そしてどのようにFULL JOIN
適合しますか?
27 に答える
重複のない列で結合していると仮定すると、これは非常に一般的なケースです。
例
それぞれ 1 つの列を持つ 2 つのテーブルがあり、次のようなデータがあるとします。
A B
- -
1 3
2 4
3 5
4 6
(1,2) は A に固有、(3,4) は共通、(5,6) は B に固有であることに注意してください。
内部結合
同等のクエリのいずれかを使用した内部結合により、2 つのテーブルの共通部分、つまり共通の 2 つの行が得られます。
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
左外部結合
左外部結合は、A のすべての行に加えて、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
右外部結合
右外部結合は、B のすべての行に加えて、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
完全外部結合
完全な外部結合では、A と B の結合、つまり、A のすべての行と B のすべての行が得られます。A の何かが B に対応するデータを持たない場合、B の部分は null であり、その逆です。逆。
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
ベン図は私にはあまり役に立ちません。
たとえば、相互結合と内部結合の区別を示していないか、より一般的には、さまざまな種類の結合述語の違いを示したり、それらがどのように動作するかについて推論するためのフレームワークを提供したりします。
論理的な処理を理解することに代わるものはなく、とにかく理解するのは比較的簡単です。
- クロス結合を想像してください。
on
ステップ 1 のすべての行に対して句を評価し、述語が評価される行を保持します。true
- (外部結合の場合のみ) ステップ 2 で失われた外部行を追加し直します。
(注: 実際には、クエリ オプティマイザーは、上記の純粋に論理的な説明よりも効率的なクエリ実行方法を見つけることができますが、最終的な結果は同じでなければなりません)
完全な外部結合のアニメーション バージョンから始めます。さらに説明が続きます。
説明
ソース テーブル
最初にCROSS JOIN
(AKA デカルト積) から始めます。これにはON
句がなく、単純に 2 つのテーブルのすべての行の組み合わせを返します。
SELECT A.Color, B.Color FROM A CROSS JOIN B
内部結合と外部結合には、「ON」句の述語があります。
- 内部結合。クロス結合結果のすべての行について、「ON」句の条件を評価します。true の場合、結合された行を返します。それ以外の場合は破棄します。
- 左外部結合。内部結合と同じで、何も一致しなかった左側のテーブルの行に対して、右側のテーブルの列に NULL 値を出力します。
- 右外部結合。内部結合と同じで、右側のテーブルで何も一致しなかった行については、左側のテーブルの列に NULL 値が出力されます。
- 完全外部結合。内部結合と同じで、左外部結合のように左の一致しない行を保持し、右外部結合のように右の一致しない行を保持します。
いくつかの例
SELECT A.Colour, B.Colour FROM A INNER B ON A.Colour = B.Colour
上記は古典的な等結合です。
アニメ版
SELECT A.Colour, B.Colour FROM A INNER B ON A.Colour NOT IN ('Green','Blue')
内部結合条件は必ずしも等価条件である必要はなく、両方 (またはどちらか) のテーブルから列を参照する必要もありません。A.Colour NOT IN ('Green','Blue')
交差結合の各行を評価すると戻ります。
SELECT A.Color, B.Colour FROM A INNER JOIN B ON 1 =1
結合条件は、クロス結合結果のすべての行に対して true と評価されるため、これはクロス結合とまったく同じです。16行の写真はもう繰り返さない。
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour
外部結合は、内部結合と同じ方法で論理的に評価されますが、左側のテーブルの行 (左側の結合の場合) が右側のテーブルの行とまったく結合しない場合は、結果にNULL
値が保持されます。右側の列。
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour IS NULL
これは、前の結果を単純に制限して、B.Colour IS NULL
. この特定のケースでは、これらは右側のテーブルで一致しなかったため保持された行になり、クエリは table で一致しない単一の赤い行を返しますB
。これは、反セミ結合として知られています。
このパターンが正しく機能し、たまたまその値を持つ行を戻すことを避けるためにIS NULL
、null 許容でないか、結合条件によってすべての値が除外されることが保証されているテスト用の列を選択することが重要です。一致しない行に加えて列。NULL
NULL
SELECT A.Colour, B.Colour FROM A RIGHT OUTER JOIN B ON A.Colour = B.Colour
右外部結合は、右テーブルの一致しない行を保持し、左側の列を null 拡張することを除いて、左外部結合と同様に機能します。
SELECT A.Colour, B.Colour FROM A FULL OUTER JOIN B ON A.Colour = B.Colour
完全外部結合は、左右の結合の動作を組み合わせて、左右のテーブルの一致しない行を保持します。
SELECT A.Colour、B.Colour FROM A FULL OUTER JOIN B ON 1 = 0
交差結合内に1=0
述部と一致する行がありません。両側のすべての行は、反対側のテーブルの列に NULL を指定した通常の外部結合ルールを使用して保持されます。
SELECT COALESCE(A.Colour, B.Colour) AS Color FROM A FULL OUTER JOIN B ON 1 = 0
前のクエリを少し修正するUNION ALL
と、2 つのテーブルのいずれかをシミュレートできます。
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour WHERE B.Colour = 'Green'
WHERE
節 (存在する場合) は論理的に結合後に実行されることに注意してください。一般的なエラーの 1 つは、左外部結合を実行してから、一致しない行を除外することになる右側のテーブルの条件を含む WHERE 句を含めることです。上記は外部結合を実行することになります...
...そして、「Where」句が実行されます。NULL= 'Green'
は true と評価されないため、外部結合によって保持された行は (青色の行と共に) 破棄され、結合を内部結合に効果的に変換します。
Color が Green の B からの行のみを含め、A からのすべての行を含めることを意図した場合、正しい構文は次のようになります。
SELECT A.Colour, B.Colour FROM A LEFT OUTER JOIN B ON A.Colour = B.Colour AND B.Colour = 'Green'
SQL フィドル
結合は、2 つのテーブルのデータを結合するために使用され、結果として新しい一時テーブルが作成されます。結合は、結合を実行するために使用する条件を指定する、述語と呼ばれるものに基づいて実行されます。内部結合と外部結合の違いは、内部結合は結合述語に基づいて実際に一致する行のみを返すことです。たとえば、Employee テーブルと Location テーブルを考えてみましょう。
従業員
従業員 ID | 従業員名 |
---|---|
13 | ジェイソン |
8 | アレックス |
3 | RAM |
17 | バブ |
25 | ジョンソン |
位置
従業員 ID | 雇用場所 |
---|---|
13 | サンノゼ |
8 | ロサンゼルス |
3 | プネー、インド |
17 | チェンナイ、インド |
39 | バンガロール、インド |
内部結合:-内部結合は、結合述語に基づいて 2 つのテーブル ( EmployeeとLocation ) の列の値を組み合わせて、新しい結果テーブルを作成します。このクエリは、 Employeeの各行をLocationの各行と比較して、結合述語を満たすすべての行のペアを見つけます。結合述語が NULL 以外の値と一致することで満たされる場合、一致したEmployeeとLocationの各行ペアの列値が結果行に結合されます。内部結合の SQL は次のようになります。
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
さて、その SQL を実行した結果は次のようになります。
Employee.EmpId | 従業員.EmpName | Location.EmpId | Location.EmpLoc |
---|---|---|---|
13 | ジェイソン | 13 | サンノゼ |
8 | アレックス | 8 | ロサンゼルス |
3 | RAM | 3 | プネー、インド |
17 | バブ | 17 | チェンナイ、インド |
外部結合:- 外部結合では、結合された 2 つのテーブルの各レコードが一致するレコードを持つ必要はありません。結合されたテーブルは、他に一致するレコードが存在しない場合でも、各レコードを保持します。外部結合は、保持されるテーブルの行 (左または右) に応じて、さらに左外部結合と右外部結合に分割されます。
左外部結合:-テーブルEmployeeおよびLocation の左外部結合 (または単に左結合) の結果には、結合条件で一致するレコードが見つからない場合でも、常に「左」テーブル ( Employee ) のすべてのレコードが含まれます。 「右側」のテーブル ( Location )。上記の表を使用すると、左外部結合の SQL は次のようになります。
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
さて、この SQL を実行した結果は次のようになります。
Employee.EmpId | 従業員.EmpName | Location.EmpId | Location.EmpLoc |
---|---|---|---|
13 | ジェイソン | 13 | サンノゼ |
8 | アレックス | 8 | ロサンゼルス |
3 | RAM | 3 | プネー、インド |
17 | バブ | 17 | チェンナイ、インド |
25 | ジョンソン | ヌル | ヌル |
Johnson は従業員の場所のテーブルにエントリがありませんが、結果には含まれていますが、場所のフィールドは null になっていることに注意してください。
右外部結合:- 右外部 結合 (または右結合) は、テーブルの処理が逆であることを除いて、左外部結合によく似ています。「右側」のテーブル ( Location ) のすべての行は、結合されたテーブルに少なくとも 1 回表示されます。「左側」のテーブル ( Employee ) に一致する行が存在しない場合、 Locationに一致しないレコードのEmployeeの列に NULL が表示されます。SQL は次のようになります。
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
上記の表を使用して、右外部結合の結果セットがどのようになるかを示すことができます。
Employee.EmpId | 従業員.EmpName | Location.EmpId | Location.EmpLoc |
---|---|---|---|
13 | ジェイソン | 13 | サンノゼ |
8 | アレックス | 8 | ロサンゼルス |
3 | RAM | 3 | プネー、インド |
17 | バブ | 17 | チェンナイ、インド |
ヌル | ヌル | 39 | バンガロール、インド |
バンガロールで働いている従業員はリストされていませんが、結果には従業員フィールドが無効になっていることに注意してください。
完全外部結合:- 完全外部結合または完全結合は、結合の結果に一致しない行を含めることにより、一致しない情報を保持し、完全外部結合を使用します。他のテーブルに一致する値があるかどうかに関係なく、両方のテーブルのすべての行が含まれます。
Employee.EmpId | 従業員.EmpName | Location.EmpId | Location.EmpLoc |
---|---|---|---|
13 | ジェイソン | 13 | サンノゼ |
8 | アレックス | 8 | ロサンゼルス |
3 | RAM | 3 | プネー、インド |
17 | バブ | 17 | チェンナイ、インド |
25 | ジョンソン | ヌル | ヌル |
ヌル | ヌル | 39 | バンガロール、インド |
内部結合
一致した行のみを取得します。つまり、A intersect B
.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
左外部結合
最初のテーブルからすべてのレコードを選択し、結合されたキーに一致する 2 番目のテーブルのすべてのレコードを選択します。
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
完全外部結合
2 番目のテーブルからすべてのレコードを選択し、結合されたキーに一致する最初のテーブルのすべてのレコードを選択します。
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
参考文献
簡単に言えば:
内部結合は、一致した行のみを取得します。
外部結合は、あるテーブルから一致した行を取得し、他のテーブルのすべての行を取得します....結果は、使用しているテーブルによって異なります。
Left : 右側のテーブルの一致した行と左側のテーブルのすべての行
右: 左側のテーブルの一致した行と右側のテーブルのすべての行または
Full : すべてのテーブルのすべての行。一致するかどうかは問題ではない
内部結合は、結合の反対側(右側)に一致するレコードがある場合にのみ行を表示します。
(左側の)外部結合は、結合の反対側(右側)に一致する行がない場合でも、左側に各レコードの行を表示します。一致する行がない場合、反対側(右側)の列にはNULLが表示されます。
内部結合では、関連するIDを持つレコードが結合テーブルに存在する必要があります。
外部結合は、右側に何も存在しない場合でも、左側のレコードを返します。
たとえば、OrdersテーブルとOrderDetailsテーブルがあります。それらは「OrderID」によって関連付けられています。
注文
- OrderID
- 顧客名
注文詳細
- OrderDetailID
- OrderID
- 商品名
- 数量
- 価格
リクエスト
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
OrderDetailsテーブルにも何かがあるOrdersのみを返します。
OUTERLEFTJOINに変更した場合
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
次に、OrderDetailsレコードがない場合でも、Ordersテーブルからレコードを返します。
これを使用して、のようなwhere句を追加することにより、孤立した注文の可能性を示すOrderDetailsがない注文を見つけることができますWHERE OrderDetails.OrderID IS NULL
。
簡単に言えば:
内部結合-> 親テーブルの主キーが子テーブルの外部キーと一致する場合に、親テーブルと子テーブルから共通のレコードのみを取得します。
左結合->
疑似コード
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.
}
}
右結合: 左結合の正反対。Right join の右側の LEFT JOIN にテーブルの名前を入れると、 LEFT JOIN と同じ出力が得られます。
外部結合: 両方のテーブルのすべてのレコードを表示しますNo matter what
。左側のテーブルのレコードがプライマリ、外部キーに基づいて右側のテーブルと一致しない場合は、結合の結果として NULL 値を使用します。
例 :
2つのテーブルがあると仮定しましょう
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
ここで、employees テーブルはマスター テーブル、phone_numbers_employees は子テーブルです (その子テーブルemp_id
に接続する外部キーとして含まれています)。employee.id
内部結合
従業員テーブルの主キー(id)が子テーブル phone_numbers_employees(emp_id) の外部キーと一致する場合にのみ、2 つのテーブルのレコードを取得します。
したがって、クエリは次のようになります。
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;
ここでは、上記で説明したように、主キー = 外部キーで一致する行のみを取得します。主キー = 外部キーで一致しない行は、結合の結果としてスキップされます。
左結合:
左結合では、右側のテーブルに一致する行があるかどうかに関係なく、左側のテーブルのすべての行が保持されます。
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;
外部結合:
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;
図的には次のようになります。
INNER JOIN
一致する両方のテーブルからすべての行を返すために使用します。つまり、結果のテーブルでは、すべての行と列に値が含まれます。
結果のテーブルにはOUTER JOIN
、空の列が含まれる場合があります。外部結合は または のいずれLEFT
かRIGHT
です。
LEFT OUTER JOIN
2 番目のテーブルに一致するものがなくても、最初のテーブルのすべての行を返します。
RIGHT OUTER JOIN
最初のテーブルに一致するものがなくても、2 番目のテーブルからすべての行を返します。
INNER JOIN
2つのテーブルを比較する際に少なくとも一致する必要があります。たとえば、テーブルAとテーブルBは、A ٨ B(A交差点B)を意味します。
LEFT OUTER JOIN
とLEFT JOIN
同じです。これにより、両方のテーブルで一致するすべてのレコードと、左側のテーブルのすべての可能性が提供されます。
同様に、RIGHT OUTER JOIN
とRIGHT JOIN
は同じです。これにより、両方のテーブルで一致するすべてのレコードと、適切なテーブルのすべての可能性が提供されます。
FULL JOIN
重複の有無LEFT OUTER JOIN
の組み合わせです。RIGHT OUTER JOIN
他の回答では、パフォーマンスとオプティマイザーに関する詳細はあまりわかりません。
のみが連想的であることを知っておくと良い場合がありINNER JOIN
ます。これは、オプティマイザーがそれを操作するオプションが最も多いことを意味します。結合順序を並べ替えて、同じ結果をより速く保つことができます。オプティマイザーは、ほとんどの結合モードを使用できます。
通常INNER JOIN
、異なる種類の結合の代わりに使用することをお勧めします。(もちろん、期待される結果セットを考慮して可能であれば。)
この奇妙な連想動作について、いくつかの良い例と説明があります。
の正確なアルゴリズムは次INNER JOIN
のLEFT/RIGHT OUTER JOIN
とおりです。
- 最初のテーブルから各行を取得します。
a
- その横にある 2 番目のテーブルのすべての行を検討してください。
(a, b[i])
ON ...
各ペアに対して句を評価します。ON( a, b[i] ) = true/false?
- 条件が と評価された場合、
true
その結合された行を返し(a, b[i])
ます。 - 一致せずに 2 番目のテーブルの最後に到達すると、これは他のテーブルのすべての列を使用して(仮想)ペアを
Outer Join
返します: LEFT 外部結合またはRIGHT 外部結合の場合。これは、最初のテーブルのすべての行が最終結果に存在することを確認するためです。Null
(a, Null)
(Null, b)
- 条件が と評価された場合、
注:句で指定される条件はON
何でもかまいません。主キーを使用する必要はありません (また、両方のテーブルから常に列を参照する必要はありません)。例えば:
... ON T1.title = T2.title AND T1.version < T2.version
( => 使用例としてこの投稿を参照してください:列に最大値を持つ行のみを選択してください)... ON T1.y IS NULL
... ON 1 = 0
(サンプルとして)
注:左結合 = 左外部結合、右結合 = 右外部結合。
簡単な言葉で、
1. INNER JOIN OR EQUI JOIN :両方のテーブルの条件のみに一致する結果セットを返します。
2. OUTER JOIN :条件が一致するかどうかにかかわらず、両方のテーブルからすべての値の結果セットを返します。
3. LEFT JOIN :左側のテーブルのすべての値と、右側のテーブルの条件に一致する行のみの結果セットを返します。
4. RIGHT JOIN :右側のテーブルのすべての値と、左側のテーブルの条件に一致する行のみの結果セットを返します。
5. FULL JOIN :完全結合と完全外部結合は同じです。
このトピックについては、Stack Overflow を含め、多くの誤った情報があります。
left join on
(aka ) は、sによって拡張された左テーブルの行と一致しない行をleft outer join on
返します。inner join on
union all
null
right join (on
別名 ) は、sによって拡張された一致しない右側のテーブル行を返しright outer join on
ます。inner join on
union all
null
full join on
(aka ) sによって拡張された一致しない左テーブルの行sによって拡張された一致しない右テーブルの行をfull outer join on
返します。inner join on
union all
null
union all
null
(SQL Standard 2006 SQL/Foundation 7.7 構文規則 1、一般規則 1 b、3 c & d、5 b.)
outer join
そのため、基礎となるものが何であるかを知るまではしないでくださいinner join
。
どの行inner join on
が返されるかを調べる:
SQL での CROSS JOIN と INNER JOIN
これは、ベン図のような図が内部結合と外部結合に役立たない理由も説明しています。
ベン図に似た図が結合に役立たない理由の詳細については
、自然結合のベン図を参照してください。
inner join
との違いouter join
は次のとおりです。
Inner join
は一致するタプルに基づいてテーブルを結合する結合ですが、outer join
は一致するタプルと一致しないタプルの両方に基づいてテーブルを結合する結合です。Inner join
は、一致しない行が省略された 2 つのテーブルの一致した行をマージしますが、2 つのテーブルの行をマージし、一致しない行はouter join
null 値で埋められます。Inner join
は交差操作にouter join
似ていますが、ユニオン操作に似ています。Inner join
は 2 種類ですが、outer join
は 3 種類です。outer join
よりも高速ですinner join
。
デモンストレーション
設定
psql
猫と人間の小さなデータベースに飛び込んで作成します。このセクション全体をコピーして貼り付けることができます。
CREATE DATABASE catdb;
\c catdb;
\pset null '[NULL]' -- how to display null values
CREATE TABLE humans (
name text primary key
);
CREATE TABLE cats (
human_name text references humans(name),
name text
);
INSERT INTO humans (name)
VALUES ('Abe'), ('Ann'), ('Ben'), ('Jen');
INSERT INTO cats (human_name, name)
VALUES
('Abe', 'Axel'),
(NULL, 'Bitty'),
('Jen', 'Jellybean'),
('Jen', 'Juniper');
クエリ
[SOMETHING JOIN]
これは、結果を確認するためにさまざまなタイプに変更して、数回実行するクエリです。
SELECT
humans.name AS human_name,
cats.name AS cat_name
FROM humans
[SOMETHING JOIN] cats ON humans.name = cats.human_name
ORDER BY humans.name;
AnINNER JOIN
は、人間と猫のすべてのペアを返します。猫のいない人間、または人間のいない猫は除外されます。
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
Aは、どちらの側にも一致がない場合にFULL OUTER JOIN
、すべての人間とすべての猫を返します。NULL
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
ALEFT OUTER JOIN
はすべての人間を返します (左の表)。猫を飼っていない人間NULL
は、cat_name
列に を取得します。人間のいない猫は除外されます。
human_name | cat_name
------------+-----------
Abe | Axel
Ann | [NULL]
Ben | [NULL]
Jen | Jellybean
Jen | Juniper
ARIGHT OUTER JOIN
はすべての猫を返します (右のテーブル)。人間のいない猫NULL
は、human_name
列に を取得します。猫のいない人間は除外されます。
human_name | cat_name
------------+-----------
Abe | Axel
Jen | Jellybean
Jen | Juniper
[NULL] | Bitty
インナー vs アウター
INNER JOIN
は一致するペアのみを取得しますが、各種類のOUTER
結合には一致しないアイテムがいくつか含まれていることがわかります。
ただし、実際の単語INNER
とOUTER
はクエリに表示する必要はありません。
JOIN
それ自体が意味するINNER
LEFT JOIN
、RIGHT JOIN
そしてOUTER JOIN
すべてが暗示するOUTER