質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • SQL

    2330questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

  • Oracle Database 11g

    191questions

    Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。

条件はwhere句に書くべきか?

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 741

lupus_dingo

score 251

お世話になっております。
条件はwhere句、結合条件はon句に書くと思いますが、
全てをon句に書くのはよくないでしょうか?

個人的な意見ですが、テーブル数が多い場合、
from句に指定されたテーブルはwhere句、それ以外のjoinで指定されたテーブルの条件は全てon句に書いた方が、どのテーブルの属性なのかはっきりするので見やすいと思っています。

外部結合が入らないことと、実行計画に変わりがないことが前提ですがみなさんどうしていますか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

+2

外部結合の場合は「実行結果」が変わってしまうので、使い分ける必要があります。

OUTER JOINのONに書く条件とWHERE句に書く条件とでは、条件の意味合いが違うんだな

内部結合の場合は実行結果は変わりません。

「実行計画」については、変わる可能性があります。SQLの文法上の意味としては、ONに記述する条件は結合の際に適用され、WHEREに記述する条件は結合した後の結果に適用されることになっているからです(外部結合で結果が変わる原因)。しかし、最近のデータベースのオプティマイザであれば内部結合の場合は結果が同じになることを理解しており、EXPLAINしてみるとWHERE句に記述した条件も通常効率がよくなる結合の際 or 前に適用されているはずです。実際に実行計画が変わることはほぼないと考えています

私が内部結合のSQLを書く場合は、論理データモデルとして結合の中心として考えるテーブル、通常FROM句の最初に指定するテーブルに適用する条件であれば、意味合いとしてそれは結合条件というよりは抽出条件であると捉えてWHERE句に記述します(実際にどれを駆動表とするかはオプティマイザが選択するのですが)。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/14 07:41

    回答ありがとうございます。
    すみません、join は内部結合限定です。説明不足で申し訳ありません。

    またDBはoracle11gのためCBOによりチューニングが入っているため実行計画が最適化されています。

    キャンセル

checkベストアンサー

0

一番理解されるのはベン図と同じように記述することだと思います。

ですが、そのままの記述とすると冗長だったりするので、記述する際には頭の片隅にある程度ですね。

私の回答としては、whereとjoinどちらに記述するかは、読みやすさや好み以前に、実行計画を最優先です。

terateilでの回答する場合なども、実際の実行計画など知る由もない訳ですが、チューニングするとしても追加・変更が少なくて済みそうな記述をある程度は意識しています。

過去にSQLに対して修正が行われた時に、性能が劣化した時がありました。
内容を確認すると、修正内容は条件の追加で、サブクエリーでネストしているSQLだったので、該当するネスト内にwhere条件を追加する修正を行っていました。
稼働後だったので、インデックスの追加は行わず、条件をネストの一番外側になるように修正。

上記などは、後から見ると説明なしでは、なんで?ってなりますよね。
もう一度、修正の機会があって読みやすさを考えて記述の修正だけをされたりしたら、逆戻りです。

なので、そのような記述をおこなう理由の説明も重要ということで。

oracle 優先ということならご存知かもしれませんが、以下参考に。
第9回 良いSQLについて

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/15 08:46

    回答ありがとうございます。
    もちろん実行計画が最優先ですね。
    私の環境では、sqlは結合しようがin句にしようがexistsにしようが実行計画が変わらなかったので質問しました。
    副問合せのネストは特に実行計画がおかしなことになる可能性が高いので出来るなら全て並列化したいですね。

    キャンセル

  • 2017/09/15 08:51

    DATABASE LINK で異なるインスタンスのテーブル同士の結合だったら、多分実行計画変わると思いますよ。

    キャンセル

  • 2017/09/17 16:18

    そうなんですね。知りませんでした。
    私の環境では他スキーマが多い割にdbリンクを使う機会はほとんどないですが、
    変わるというのはdbリンクを含んだsqlの場合、実行計画が安定しないということでしょうか?

    キャンセル

  • 2017/09/17 19:03

    単純にテーブル同士をjoinすると、極端に言うとjoinの為に1件ごとにトラフィックが発生している感じで、非常に時間が掛かっていました。
    なので、リンク先のテーブルを(select * from xxx)のようなサブクエリーと結合することで、トラフィックの発生回数を抑えることができました。
    スナップショットであれば、そういうことは無いでしょうけど。
    かなり前なので、改善されているかもしれませんけれど。

    キャンセル

  • 2017/09/18 11:09

    必要な他スキーマのテーブルを直接dbリンクで結合するのではなく、そのスキーマ内で必要なテーブルを全てまとめたビューをdbリンクとして結合するということでしょうか?

    ちなみにスナップショット知らなかったのでみましたが、マテビューみたいなものでしょうか。

    キャンセル

  • 2017/09/18 16:46

    ビューではありません。サブクエリーです。
    DATABASE LINKやスナップショットはここでは書ききれないので、御自身で調べてみて下さい。

    キャンセル

  • 2017/09/22 08:26

    直接join xxx@linkではなく、
    join (select * from xxx@link)
    ということでしょうか?

    キャンセル

  • 2017/09/22 09:19

    そうです。
    join している項目であっても、データ量を減らすために、サブクエリー内でのwhere条件で絞り込んだりすることもあります。

    キャンセル

  • 2017/09/25 08:46

    ありがとうございます。
    参考にします。

    キャンセル

0

実行計画に変わりがないことが前提

「実行結果に変わりがない」の間違いでしょうか?
条件をwhereまたはonにすることで実行計画が変わると思います。
経験上、MySQLではあまり使うことがないですが、PostgreSQLでは速度が劇的に改善することがあったような。

例えばテーブルAとBの1万件同士を結合して結果が10件のクエリを考えると

  • AとBを結合した1万件のデータからwhere条件に一致する10件を抽出
  • Bをonの条件で10件抽出してからAと結合

このような方法で抽出することが可能になるのではないでしょうか。後者のほうが速そうです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/14 07:42

    回答ありがとうございます。
    すみません、join は内部結合限定です。説明不足で申し訳ありません。

    またDBはoracle11gのためCBOによりチューニングが入っているため実行計画が最適化されています。

    キャンセル

0

実行結果は変わりますよ。
バグの元になっているのに気が付かないでいる人もいます。
外部結合におけるONとWHEREの違い
ON 句は結合条件、WHERE 句は抽出条件

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/14 07:37

    回答ありがとうございます。
    すみません、join は内部結合限定です。説明不足で申し訳ありません。

    キャンセル

  • 2017/09/16 11:23

    内部結合で設計したけど実際にデータがそろったら外部結合にしないといけなかったとか、その逆の場合も良くあることです。その時バグを起こしにくいように準備しておくことも大切なことです。

    キャンセル

  • 2017/09/17 16:15

    ありがとうございます。心がけます。

    キャンセル

0

大抵のDBエンジンは実行計画の最適化をするのでどうやっても内部的にはかわらないようです
Oracleはよくわかりませんが、たとえばMySQLなどだとテーブル同士の直接リレーションしない
データをorで検索する時若干処理効率がかわるようです

select * from a inner join b on a.x=b.x and (a.y=1 or b.z=2);
select * from a inner join b on a.x=b.x where a.y=1 or b.z=2;

まぁあまり想定されないような使い方なので気にすることはないと思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/15 08:39

    回答ありがとうございます。
    mysqlでも最適化されるんですね。
    sqlを組み立てる場合はとりあえず実行計画を確認するのがよいですね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    MySQLについておしえてください 

    MySQLについて教えて下さい。 AとBのテーブルがあり AとBで比較する際 AにはあってBにはない ときの条件はどのようにしたらいいでしょうか。

  • 解決済

    3つのテーブルを結合した後の値の取得について教えて下さい。

    PHPを使って、データベースの値を取得しようとしています。 2つのテーブルを結合後、値の取得はできるのですが、3のテーブルを結合した場合 bool(false) という、エラーが

  • 解決済

    mysqlでグループごとに5行以上存在する行を全て表示

    こんにちは。 MySQL 5.6.17を使用しております。 user  date   a    2015/01/01   a    2015/01/02   a    2015/

  • 解決済

    SQL構文でlikeとinと不等式を組み合わせたような構文

    MySQLで、あるカラム(カラム名は「floorplan」とします)に以下のデータが入っていたとします。 1K,1K,1K,2DK,3DK,3DK,3LDK,3LDK,4DK,4

  • 受付中

    ActiveRecordでJOIN結果を返したい

    ActiveRecord単体で使ってます。 joinしたいのですが、戻り値は一つのテーブルですよね これを他のテーブルのカラムを受け取るにはどうしたら良いのでしょうか? 中間

  • 解決済

    SQL 重複していない行の抽出

    以下の2つの条件でデータを検索したいのですがうまくいきません。 子テーブルのa列にある値は基本的に親テーブルのA列に属していなければならないが、属していないものがある。それ

  • 解決済

    mysql select文の処理

    指定したカラムの値が同じレコードを複数抽出して、そのレコードの別のカラム名で別のテーブルとリレーションしたい時のSQL文はどのようになりますか? CUSTOMER_NOが同じ

  • 受付中

    UPDATE文の副問合せ

    テーブルAのa列と、テーブルBのa列を結合し、 『テーブルAのb列がアで、テーブルBのb列がイの場合、テーブルBのb列をイからアへ更新』というような指示を出したいです。 w

同じタグがついた質問を見る

  • SQL

    2330questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

  • Oracle Database 11g

    191questions

    Oracle DatabaseはRDBMSの商品です。具体的な発売商品として知られているのが、 Oracle9i、Oracle10g、Oracle 11gとOracle 12cです。