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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Oracle Database 11g

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

SQL

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

Q&A

解決済

5回答

1287閲覧

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

lupus_dingo

総合スコア257

Oracle Database 11g

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

SQL

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

0グッド

2クリップ

投稿2017/09/13 11:06

編集2017/09/13 22:44

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

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

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

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

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

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

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

投稿2017/09/13 12:39

編集2017/09/13 12:56
SVC34

総合スコア1149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2017/09/13 22:41

回答ありがとうございます。 すみません、join は内部結合限定です。説明不足で申し訳ありません。 またDBはoracle11gのためCBOによりチューニングが入っているため実行計画が最適化されています。
guest

0

ベストアンサー

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

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

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

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

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

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

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

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

投稿2017/09/14 01:05

編集2017/09/14 01:56
sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2017/09/14 23:46

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

2017/09/14 23:51

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

2017/09/17 07:18

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

2017/09/17 10:03

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

2017/09/18 02:09

必要な他スキーマのテーブルを直接dbリンクで結合するのではなく、そのスキーマ内で必要なテーブルを全てまとめたビューをdbリンクとして結合するということでしょうか? ちなみにスナップショット知らなかったのでみましたが、マテビューみたいなものでしょうか。
sazi

2017/09/18 07:46

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

2017/09/21 23:26

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

2017/09/22 00:19

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

2017/09/24 23:46

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

0

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

SQL

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

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

投稿2017/09/14 01:05

yambejp

総合スコア114843

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2017/09/14 23:39

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

0

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

投稿2017/09/13 21:13

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2017/09/13 22:37

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

2017/09/16 02:23

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

2017/09/17 07:15

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

0

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

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

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

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

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

投稿2017/09/13 11:30

kodai

総合スコア759

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lupus_dingo

2017/09/13 22:42

回答ありがとうございます。 すみません、join は内部結合限定です。説明不足で申し訳ありません。 またDBはoracle11gのためCBOによりチューニングが入っているため実行計画が最適化されています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問