web-dev-qa-db-ja.com

JOINを使用する場合のWHERE句とON

次のT-SQLコードがあるとします。

SELECT * FROM Foo f
INNER JOIN Bar b ON b.BarId = f.BarId;
WHERE b.IsApproved = 1;

次のコードも同じ行のセットを返します。

SELECT * FROM Foo f
INNER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);

これはここでの最良の例ではないかもしれませんが、これら2つの間にパフォーマンスの違いはありますか?

41
tugberk

いいえ、クエリオプティマイザーは両方の例で同じ実行プランを選択できるほどスマートです。

SHOWPLANを使用して実行プランを確認できます。


それでも、すべての結合接続はON句に、すべての制限はWHERE句に置く必要があります。

30
aF.

外部結合との違いに注意してください。 ONJOIN条件にb.IsApproved(右側のテーブルではBar)のフィルターが追加されたクエリ:

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId); 

[〜#〜]ではない[〜#〜]は、WHERE句にフィルターを配置するのと同じです:

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1); 

Barへの「失敗した」外部結合(つまり、b.BarIdf.BarIdがない場合)のため、このような失敗したすべての結合行のb.IsApprovedNULLのままになり、これらの行は除外された。

これを別の見方で見ると、最初のクエリでは、LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)は常にLEFTテーブル行を返します。これは、LEFT OUTER JOINは、結合が失敗した場合でもLEFTテーブル行が返されることを保証するためです。ただし、(b.IsApproved = 1)条件にLEFT OUTER JOINを追加すると、(b.IsApproved = 1)がfalseの場合、つまり、LEFT JOIN(b.BarId = f.BarId)条件に通常適用されるのと同じルールに従って、右側のテーブル列がNULLになります。

更新:コンラッドが尋ねた質問を完了するには、オプションフィルターの同等のLOJは次のようになります。

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);

つまり、WHERE句は、結合が失敗するかどうかの条件(NULL)とフィルターが無視される条件、および結合が成功し、フィルターを適用する必要がある場所の両方を考慮する必要があります。 (b.IsApprovedまたはb.BarIdNULLでテストできます)

SqlFiddleをここにまとめます を使用して、JOINに対するb.IsApprovedフィルターのさまざまな配置の違いを示します。

43
StuartLC
SELECT * FROM Foo f
INNER JOIN Bar b ON b.BarId = f.BarId
WHERE b.IsApproved = 1;

これがより良いフォームです。読みやすく、変更も簡単です。ビジネスの世界では、これはあなたがやりたいことです。ただし、パフォーマンスに関しては同じです。

6
Landin Martens

私は、4つのテーブルに対してクエリのテストを実行しました-1つのプライマリテーブルに3つのINNER JOINと合計4つのパラメーターがあり、両方のアプローチの実行プランを比較しました(JOINのONのフィルター条件を使用して、さらにWHERE句)。

実行計画はまったく同じです。これはSQL Server 2008 R2で実行しました。

0
Jason L

最近のバージョンのMSSQLでもオプティマイザが十分にスマートではない場合がいくつかありますが、パフォーマンスの違いはひどいものでした。

しかし、これは例外であり、ほとんどの場合、SQL Serverオプティマイザは問題を解決して適切な計画を立てます。

そのため、WHERE句でフィルターを使用するポリシーを維持し、必要に応じて最適化します。

0
Fabricio Araujo