web-dev-qa-db-ja.com

テーブル左結合時のwhere句とon句の違いは何ですか?

SQL1:

select t1.f1,t2.f2 
from t1 
   left join t2 on t1.f1 = t2.f2 and t1.f2=1 and t1.f3=0 

SQL2:

select t1.f1,t2.f2 
from t1 
  left join t2 on t1.f1 = t2.f2 
where t1.f2=1 and t1.f3=0

違いはwhereとon句ですが、同じ戻り結果がありますか?そして、違いは何ですか? DBMSはそれらを同じ方法で実行しますか?ありがとう。

21
SleeplessKnight

where句は結果セット全体に適用されます。 on clauseは問題の結合にのみ適用されます。

提供されている例では、結合の内側のフィールドに関連するすべての追加条件-この例では、2つのクエリは実質的に同一です。

ただし、結合のouter側のテーブルの値に条件を含めた場合は、大きな違いが生じます。

あなたはこのリンクからもっと得ることができます: http://ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

例えば:

select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 and t2.f4=1

select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 where t2.f4=1

-異なることを行う-前者はf2が1であるt2レコードへの結合を残し、後者は事実上t2への内部結合に戻されました。

24
user359040

最初のクエリは、2番目のクエリよりも結合条件がより具体的であるため、2番目のクエリよりも高速です。where句でフィルタリングするレコードを返すことは意味がありません(それらをまったく返さない方が良いでしょう。query1 )

とにかく、それは本当にクエリオプティマイザーによって異なります。

以下を見てください:

JOINはWHEREより高速ですか?

8

2つのクエリは[〜#〜] not [〜#〜]同一です。

Mark Ba​​nnisterは、where句が結果セット全体に適用されるが、on clauseが結合に適用されることを指摘したのは正解でした。

あなたの場合、SQL 1 LEFT JOIN条件の場合、フィルターは右側で結合されますが、左側は常にWHEREフィルターの前に返されます。 WHERE条件がないため、常にすべてのt1が返されます。

SQL 2では、LEFT JOIN条件が右側に表示される結果をフィルタリングしますが、再びすべてのt1が返されます。ただし、今回はWHERE条件により、t1の一部のレコードが除外される場合があります。

INSERT INTO `t1` (`f1`,`f2`,`f3`) VALUES (1,1,1); INSERT INTO `t2` (`f3`) VALUES (1);

それらは異なるロジックをポイントするため、クエリはそれに基づいて作成する必要があり、それにより大きなパワーと柔軟性が得られます。

ただし、INNER JOINは同じ結果を返すため、オプティマイザを確認してください。

2
Nicholas

1)

SQL1: select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 **and** t1.f2=1 and t1.f3=0 

この場合、パーサーはこれら3つの条件でt1の各行とt2の各行をチェックします。より速い結果を得る。

2)SQL2: select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 **where** t1.f2=1 and t1.f3=0

この場合、結合は最初の条件のみを取り、結合から得られた結果はそれらの2つの条件でフィルタリングされます。そして、最初のクエリよりも時間がかかります。

あなたはこのリンクからもっと得ることができます: http://ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

2
Somnath Muluk

リレーショナル代数を使用すると、WHERE句とINNER JOINの述語を交換できるため、WHERE句を使用したINNER JOINクエリでも、オプティマイザによって述語を再配置できるため、JOINプロセス中に述語を除外できます。

できるだけ読みやすい方法でクエリを記述することをお勧めします。

これには、INNER JOINを比較的「不完全」にすることや、いくつかの基準をWHEREに置くことで、フィルタリング基準のリストをより簡単に保守できるようにすることが含まれる場合があります。

あなたはこのリンクからもっと得ることができます: http://ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

たとえば、次の代わりに:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

書く:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

しかし、それはもちろん異なります。

2
Somnath Muluk