web-dev-qa-db-ja.com

SQL / MySQLでは、結合ステートメントの「ON」と「WHERE」の違いは何ですか?

次のステートメントは同じ結果になります(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は「二次」フィルタリングを行いますか?または、onwhereを使用するより一般的なルールはありますか?ありがとう。

44

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.idNULLを残すことができないため、送信されたことのないギフトのみが返されます。

48
Quassnoi

ON句は、テーブル間の関係を定義します。

WHERE句は、関心のある行を示します。

多くの場合、それらを交換しても同じ結果が得られますが、左外部結合の場合は常にそうとは限りません。

  • ON句が失敗した場合でも、左側のテーブルの列を含む行が取得されますが、右側のテーブルの列にはnullが含まれます。
  • WHERE句が失敗した場合、その行はまったく取得されません。
49
Mark Byers

INNER JOINを使用する場合、ONWHEREは同じ結果になります。そう、

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句でフィルタリングに使用される列を使用する必要があります。これにより、最高の読みやすさが提供されます。

14
RedFilter

結果は同じですが、「ON」は最初に結合を行い、結合されたセットのデータを取得します。取得は高速で、負荷は少なくなります。ただし、「WHERE」を使用すると、2つの結果セットが最初にフェッチされ、次に条件が適用されます。だからあなたは何が好まれているか知っています。

3
Kangkan
  • ONは、各レコードの順列の作成に使用されるセットに適用されます一部として JOIN操作
  • WHEREは、適用されるフィルターを指定しますafter the JOIN operation

実際には、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を適用する必要があります

2
Hou