none
INNER JOINで結合する場合と、WHERE句で結合する場合の違いについて RRS feed

  • 質問

  •  

    SQL Server2000で開発しています。

     

    テーブルの結合方法として、
    INNER JOINで結合する方法と
    FROM句にすべてのテーブルを記載して、WHERE句で結合する方法があると思いますが、
    この2つの方法に違いはありますか?

     

    私は全く同じなのではないかと思っているのですが。。。

     

    もしご存知でしたら、ご教示頂けませんか?
    よろしくお願い致します。

    2008年8月19日 3:04

回答

  • 実行プランで見るとどちらも同じなので、同じではないかと思います。
    2008年8月19日 5:37
  • コンドルさん、はじめまして。

     

    下記のページの下部から実行プランについての機能説明ビデオを見ることができるようです。

    http://www.microsoft.com/japan/sql/prodinfo/previousversions/techinfo/video/Tuning.mspx

     

    こういうのもありました。

    http://msdn.microsoft.com/ja-jp/library/cc707363.aspx

     

    クエリの最適化については参考書もありますしBooksOnlineにも詳細に書かれているので結合の違いについて分かるのではないかと思います。

     

    これは私の意見ですが結合するTBLのインデックスの付け方もそうですがデータ量や統計の有無など複数の要素で最適なクエリの書き方は異なるのではないかと思います。

     

    あと、SQL1,2で関数 GETDATE() が使われていましたので関数の使用についてSQL Server2008オンラインブックからの引用ですがご確認ください。

     

    http://msdn.microsoft.com/ja-jp/library/ms190642.aspx

    ------------------------------------------------------------------------------------------------------------------------------------------------------------

    可能な場合は、以下のガイドラインに従うことをお勧めします。

    1.選択可能な場合は、厳密に決定的な関数を記述します。特に、Transact-SQL 関数はスキーマ バインドにします。

    2.非決定的な関数の使用を選択リストの一番外側に検定します。

    3.パフォーマンスが重要なクエリでは、非決定的関数を使用しないでください。

    4.呼び出しの数、順序、またはタイミングは実装によって異なるので、これらに依存しないでください。

    詳細については、「決定的関数と非決定的関数」を参照してください。

    ------------------------------------------------------------------------------------------------------------------------------------------------------------

    2008年8月20日 14:57
  •  コンドル さんからの引用

    GETDATE() BETWEEN T.適用開始日 AND T.適用終了日

     

    システム日付が適用終了日当日の時、取得できなくなりますよ。

    例えば、システム日付=適用終了日:2008/08/29だとすると、

    GETDATE()では時間情報も取るので2008/08/29 12:14:01:000等になってしまいBETWEENから漏れてしまいます。

     

    CONVERT(VARCHAR, GETDATE(), 111) BETWEEN T.適用開始日 AND T.適用終了日

    にすると防げます。

     

    2008年8月29日 3:38

すべての返信

  • 実行プランで見るとどちらも同じなので、同じではないかと思います。
    2008年8月19日 5:37
  • ご回答ありがとうございます。
    実行プランで確認すれば、良いのですね。
    勉強になりました。

     


    今の質問に関連して、もうひとつ質問があります。
    もしよろしければ、ご教示下さい。

    以下の2つのSQLをクエリアナライザから実行して、統計を見ました。

    SQL1

    Code Snippet
    SELECT
     *
    FROM
     販売テーブル AS H
    INNER JOIN
     取引先テーブル AS T
    ON
     H.取引先コード = T.取引先コード
     AND GETDATE() BETWEEN T.適用開始日 AND T.適用終了日

     

     

     

    SQL2

    Code Snippet
    SELECT
     *
    FROM
     販売テーブル AS H
    INNER JOIN
     取引先テーブル AS T
    ON
     H.取引先コード = T.取引先コード
    WHERE
     GETDATE() BETWEEN T.適用開始日 AND T.適用終了日

     

     

     

    すると以下の3つの項目に関して差異がでました。

    Code Snippet

                         SQL1  SQL2
    -------------------------------------------------------------------
    SELECT ステートメントの数                  2           0
    SELECT ステートメントで処理された行数         1193           0
    ユーザー トランザクション数                      5           0

     

     


    これらの項目のヘルプを確認したのですが、
    http://msdn.microsoft.com/ja-jp/library/aa216969(SQL.80).aspx
    うまく理解できませんでした。

     

    これはSQL1では、結合処理をするたびに条件(適用期間の判断)を見るため、
    たくさんのSELECT文が実行されていて、
    処理が遅くなると判断してよろしいでしょうか?

     

     

    ご回答よろしくお願い致します。

    2008年8月19日 6:29
  • コンドルさん、はじめまして。

     

    下記のページの下部から実行プランについての機能説明ビデオを見ることができるようです。

    http://www.microsoft.com/japan/sql/prodinfo/previousversions/techinfo/video/Tuning.mspx

     

    こういうのもありました。

    http://msdn.microsoft.com/ja-jp/library/cc707363.aspx

     

    クエリの最適化については参考書もありますしBooksOnlineにも詳細に書かれているので結合の違いについて分かるのではないかと思います。

     

    これは私の意見ですが結合するTBLのインデックスの付け方もそうですがデータ量や統計の有無など複数の要素で最適なクエリの書き方は異なるのではないかと思います。

     

    あと、SQL1,2で関数 GETDATE() が使われていましたので関数の使用についてSQL Server2008オンラインブックからの引用ですがご確認ください。

     

    http://msdn.microsoft.com/ja-jp/library/ms190642.aspx

    ------------------------------------------------------------------------------------------------------------------------------------------------------------

    可能な場合は、以下のガイドラインに従うことをお勧めします。

    1.選択可能な場合は、厳密に決定的な関数を記述します。特に、Transact-SQL 関数はスキーマ バインドにします。

    2.非決定的な関数の使用を選択リストの一番外側に検定します。

    3.パフォーマンスが重要なクエリでは、非決定的関数を使用しないでください。

    4.呼び出しの数、順序、またはタイミングは実装によって異なるので、これらに依存しないでください。

    詳細については、「決定的関数と非決定的関数」を参照してください。

    ------------------------------------------------------------------------------------------------------------------------------------------------------------

    2008年8月20日 14:57
  •  

    ご回答ありがとうございます。

     

    とても参考になりました。
    ビデオは見れる環境にないので、まだ見ておりませんが。。

     

    最適化について誤解しておりました。
    詳しくご説明頂きありがとうございました。

    2008年8月21日 0:49
  •  コンドル さんからの引用

    GETDATE() BETWEEN T.適用開始日 AND T.適用終了日

     

    システム日付が適用終了日当日の時、取得できなくなりますよ。

    例えば、システム日付=適用終了日:2008/08/29だとすると、

    GETDATE()では時間情報も取るので2008/08/29 12:14:01:000等になってしまいBETWEENから漏れてしまいます。

     

    CONVERT(VARCHAR, GETDATE(), 111) BETWEEN T.適用開始日 AND T.適用終了日

    にすると防げます。

     

    2008年8月29日 3:38
  • ご指摘ありがとうございます。
    サンプルで簡単にSQLを作成していたため、
    このように書いてしまいました。

     

    ただ、とても勉強になりました。
    ご指摘の点は私も十分承知でしたが、
    GETDATE()を使用するとうまく取得できないため、
    VBなどのプログラムから現在の日付をいつも渡していたのです。
    このように書けば、SQLのみで対応できますね。
    勉強になりました。
    ありがとうございます。

     

    2008年8月29日 10:28