次のステートメントは同じ結果になります(1つはon
を使用し、もう1つはwhere
を使用しています)。
mysql> select * from gifts INNER JOIN sentGifts ON gifts.giftID = sentGifts.giftID;
mysql> select * from gifts INNER JOIN sentGifts WHERE gifts.giftID = sentGifts.giftID;
左外部結合の場合にのみ、「一致しない」ケースを見つけることができます。
(誰からも送信されなかったギフトを見つけるため)
mysql> select name from gifts LEFT OUTER JOIN sentgifts
ON gifts.giftID = sentgifts.giftID
WHERE sentgifts.giftID IS NULL;
この場合、最初にon
を使用し、次にwhere
を使用します。 on
は最初にマッチングを行い、次にwhere
は「二次」フィルタリングを行いますか?または、on
対where
を使用するより一般的なルールはありますか?ありがとう。
WHERE
は全体としてSELECT
クエリの一部であり、ON
は個々の結合の一部です。
ON
は、以前に使用されたテーブルのフィールドのみを参照できます。
左側のテーブルのレコードに実際に一致するものがない場合、LEFT JOIN
は、すべてのフィールドがNULLS
に設定された右側のテーブルから1つのレコードを返します。 WHERE
句は、これを評価してフィルタリングします。
クエリでは、 'sentgifts'に一致しないgifts
のレコードのみが返されます。
以下に例を示します
gifts
1 Teddy bear
2 Flowers
sentgifts
1 Alice
1 Bob
---
SELECT *
FROM gifts g
LEFT JOIN
sentgifts sg
ON g.giftID = sg.giftID
---
1 Teddy bear 1 Alice
1 Teddy bear 1 Bob
2 Flowers NULL NULL -- no match in sentgifts
---
SELECT *
FROM gifts g
LEFT JOIN
sentgifts sg
ON g.giftID = sg.giftID
WHERE sg.giftID IS NULL
---
2 Flowers NULL NULL -- no match in sentgifts
ご覧のとおり、実際の一致ではsentgifts.id
にNULL
を残すことができないため、送信されたことのないギフトのみが返されます。
ON
句は、テーブル間の関係を定義します。
WHERE
句は、関心のある行を示します。
多くの場合、それらを交換しても同じ結果が得られますが、左外部結合の場合は常にそうとは限りません。
ON
句が失敗した場合でも、左側のテーブルの列を含む行が取得されますが、右側のテーブルの列にはnullが含まれます。WHERE
句が失敗した場合、その行はまったく取得されません。
INNER JOIN
を使用する場合、ON
とWHERE
は同じ結果になります。そう、
select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
where t1.Name = 'John'
とまったく同じ出力になります
select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
and t1.Name = 'John'
既に述べたように、OUTER JOIN
を使用する場合はそうではありません。クエリプランが構築されるものは、データベースプラットフォームおよびクエリの詳細に依存し、変更される可能性があります。したがって、それだけで意思決定を行っても、クエリプランが保証されるわけではありません。
経験則として、ON
句でテーブルを結合する列と、WHERE
句でフィルタリングに使用される列を使用する必要があります。これにより、最高の読みやすさが提供されます。
結果は同じですが、「ON」は最初に結合を行い、結合されたセットのデータを取得します。取得は高速で、負荷は少なくなります。ただし、「WHERE」を使用すると、2つの結果セットが最初にフェッチされ、次に条件が適用されます。だからあなたは何が好まれているか知っています。
実際には、ONは条件を満たさない各フィールドをNULLに置き換えます。与えられた @ Quassnoiによる例
gifts
1 Teddy bear
2 Flowers
sentgifts
1 Alice
1 Bob
---
SELECT *
FROM gifts g
LEFT JOIN
sentgifts sg
ON g.giftID = sg.giftID
---
ON条件がなければ、LEFT JOIN順列は次のコレクションに対して計算されます。
{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {'ALICE', 'Bob'} }
g.giftID = sg.giftID
ON条件の場合、これは順列の作成に使用されるコレクションです。
{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL, NULL} }
事実上:
{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL} }
したがって、次のLEFT JOINになります。
Teddy bear Alice
Teddy bear Bob
Flowers NULL
フルアウタージョインの場合:
LEFT JOINの場合は{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL} }
、RIGHT JOINの場合は{ 'ALICE': {'Teddy bear', NULL}, 'Flowers': {'Teddy bear', NULL} }
:
Teddy bear Alice
Teddy bear Bob
Flowers NULL
ON g.giftID = 1
などの条件もある場合は、
{ NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} }
lEFT JOINの結果は
Flowers NULL
fULL OUTER JOINの場合、LEFT JOINの場合は{ NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} }
、RIGHT JOINの場合は{ 'ALICE': {NULL, NULL}, 'Flowers': {NULL, NULL} }
になります
NULL Alice
NULL Bob
Flowers NULL
注MySQLにはFULL OUTER JOINがないため、LEFT JOINとRIGHT JOINにUNIONを適用する必要があります