web-dev-qa-db-ja.com

結合基準またはより効率的なwhere句のSQLフィルター基準

2つのテーブルを結合する比較的単純なクエリがあります。 「Where」基準は、結合基準またはwhere句として表すことができます。どちらが効率的か疑問に思います。

クエリは、セールスマンが最初から昇進するまでの最大売上を見つけることです。

ケース1

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
                  and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 

ケース2

select salesman.salesmanid, max(sales.quantity)
from salesman
inner join sales  on salesman.salesmanid =sales.salesmanid 
where sales.salesdate < salesman.promotiondate
group by salesman.salesmanid 

注ケース1には、where句がまったくありません。

RDBMSはSQLServer2005です

[〜#〜] edit [〜#〜]結合基準の2番目の部分またはwhere句がsales.salesdate <ある固定日だった場合、実際には2つのテーブルを結合する基準はありません。それは答えを変えます。

25
Gratzy

ここでは、パフォーマンスを決定要因として使用しません。正直なところ、これら2つのケースの間に測定可能なパフォーマンスの違いはないと思います。

私は常にケース#2-を使用します-なぜですか?私の意見では、2つのテーブル間のJOINを確立する実際の基準のみをJOIN句に入れる必要があるため、他のすべてはWHERE句に属します。

物事をきれいに保ち、物事をそれらが属する場所に置くだけの問題、IMO。

明らかに、LEFT OUTER JOINの場合、基準の配置によって返される結果の点で違いが生じる場合があります。もちろん、これらのケースは私の推奨から除外されます。

マーク

28
marc_s

結合にハードコードされた基準があることを好みます。これにより、SQLがはるかに読みやすく移植性が高くなります。

読みやすさ:すべてのテーブル基準が結合に直接書き込まれるため、取得するデータを正確に確認できます。大規模なステートメントでは、基準は他の50の表現に埋もれている可能性があり、簡単に見落とされます。

移植性:FROM句からチャンクをコピーして、別の場所に貼り付けることができます。これにより、結合とそれに伴う必要な基準が得られます。これらの2つのテーブルを結合するときに常にその基準を使用する場合は、それを結合に入れるのが最も論理的です。

例えば:

FROM
table1 t1
JOIN table2 t2_ABC ON
  t1.c1 = t2_ABC.c1 AND
  t2_ABC.c2 = 'ABC'

表2から2番目の列を取得する必要がある場合は、そのブロックをメモ帳にコピーし、「ABC」を検索/リパルスし、新しいコードブロック全体を貼り付ける準備をします。

追加:WHERE句で変動する可能性のある基準を気にすることなく、内部結合と外部結合を簡単に変更できます。

可能な場合は、実行時の基準のためにWHERE句を厳密に予約します。

効率について:実行速度について言及している場合、他の誰もが述べているように、それは冗長です。より簡単なデバッグと再利用について言及している場合は、オプション1をお勧めします。

3
Spencer Evans

実行プランエスティメータとSQLプロファイラを実行して、それらが互いにどのように積み重なっているかを確認できます。

ただし、このSQL Server MVPによると、これらは内部的には意味的に同じです。

http://www.eggheadcafe.com/conversation.aspx?messageid=29145383&threadid=29145379

3
klabranche

その前に通知したとおり、最後に言いたいことが1つあります。どちらの方法でも同じパフォーマンスが得られるか、Where句の基準を使用すると、一部の回答に見られるように少し速くなる可能性があります。

しかし、私は1つの違いを特定しました。それは、論理的なニーズに使用できます。

  1. [〜#〜] on [〜#〜]句で基準を使用すると、選択する行がフィルタリング/スキップされません。代わりに、条件に基づいて結合列がnullになります。

  2. Where句で基準を使用すると、結果全体で行をフィルタリング/スキップできます

2
Michael Rajesh

すべての場合に当てはまる、これに対する有限の答えが見つかるとは思いません。 2つは常に交換可能であるとは限りません-一部のクエリ(一部の左結合)では、WHERE行とFROM行に基準を配置することで異なる結果が得られるためです。

あなたの場合、これらのクエリの両方を評価する必要があります。 SSMSでは、これらのクエリの両方の推定実行プランと実際の実行プランを表示できます。これは、どちらがより最適かを判断するための最初のステップとして適しています。また、時間&IO for each(set statistics time on、set statistics io on)-を表示することもできます。これにより、決定を下すための情報も得られます。

あなたの質問のクエリの場合-両方とも同じクエリプランで出てくると思います-したがって、この場合は問題ではないかもしれませんが、他の場合は異なるプランを生成する可能性があります。

これを試して、2つの違いを確認してください...

SET STATISTICS IO ON
SET STATISTICS TIME ON

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid =sales.salesmanid
       and sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

select salesman.salesmanid, 
       max(sales.quantity)
from   salesmaninner join sales on salesman.salesmanid = sales.salesmanid 
where  sales.salesdate < salesman.promotiondate
group by salesman.salesmanid

SET STATISTICS TIME OFF
SET STATISTICS IO OFF
1
Scott Ivey

ばかげているように見えるかもしれませんが、答えは、クエリアナライザが最も効率的な計画を作成するクエリです。

私の考えでは、これらは同等のように見えるため、クエリアナライザーは同じプランを生成する可能性がありますが、テストする必要があります。

0
Craig Shearer

WHEREメソッドを使用することは、これを行うための古い方法と見なされているため、どちらも効率的ではありません( http://msdn.Microsoft.com/en-us/library/ms190014.aspx )。あなたは実行計画を見て、彼らが同じことをしているのを見ることができます。

0
Bryan S.

SQL ManagementStudioの推定実行プランをよく理解してください。他の人が言っているように、あなたが何をしようとも、あなたはアナライザーに翻弄され、その見積もりを信頼します。あなたが提供した2つはまったく同じ計画を生み出すと思います。

開発文化を変える試みである場合は、より良い計画を提供するものを選択してください。同一のものについては、文化に従ってください

私はこれをこのような他の「効率」の投稿にコメントしました(これは誠実で皮肉なことです)-これがあなたのボトルネックが存在する場所である場合、あなたとあなたのチームにハイタッチします。

0
Austin Salonen

ケース1(JOINの基準)はカプセル化に適しています。通常、カプセル化を増やすことは良いことです。別のクエリへのコピー/貼り付けの省略を減らし、後でLEFT JOINに変換した場合のバグを減らし、読みやすさを向上させます(関連するものをまとめて「 WHERE句の「ノイズ」)。この場合、WHERE句は、主要なテーブル基準または複数のテーブルにまたがる基準のみをキャプチャします。

0
Pete Alvin