出産前後の痔にはご注意!

SELECT文などで、
 WHERE 条件1
 AND  条件2
と記述した場合、実行順序は上から(条件1⇒条件2)になるのでしょうか?それとも逆なのでしょうか?
同じ職場の方は、上からだとおっしゃるのですが、実行してみると下からのような気がするのですが・・・。私の気のせいでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (8件)

例えば、select * from dual where return_negative_slow() > 0 and return_negative_fast() > 0 のような場合、and を右から左に短絡評価してるような気がします。

    • good
    • 0

Oracle ではおっしゃっているように下から上に向かって解析されます。

ただ、それは構文解析のルールであって、実行計画は構文解析が終了した後に、別の方法によって行われます。従って、WHERE 句の記述順を変えたからといって実行計画が変わることはありません。

また、10gになって廃止されてしまいましたが、ルールベース・アプローチでは、FROM 句については、後ろから判定される傾向があります。ただし、これは等結合の場合のみで、外部結合があったりするとこの傾向は当てはまらなくなります。

また、ルールベース・アプローチでは、できるだけ索引を使うような実行計画を立てる傾向がありますが、このとき、使える索引が複数あったりすると、後から作成された索引を優先的に使うというようなルールもあります。

ただし、片方が主キー索引で片方が普通の索引であるような場合は、ルールに乗っ取って主キー索引が優先的に使われることに注意してください。
    • good
    • 0

#4です。



念のため書いておきますが..

ルールベースだから、FROMに書いた表を、必ず下から上に向かって、検索するというのは
間違いです。
ルールベースとコストベースで、実行計画を立てるための、決定要素は異なりますが、
ルールベースであっても、上から下へ検索するようなプランは作ります。

例えば、ルールベースオプティマイザで、次のSQLは

select * from emp,dept
where empno between 1 and 9999 and loc='DALLAS' and emp.deptno=dept.deptno

emp表->dept表の順番になります。(ルール上、empの索引検索と判断したから)

ルールベースで、よく”下から上に”と言われるのは、ルール上決定しきれない場合に、
そのような適当な判断をするからです。(=判断に窮すると、下から上に・・)

例えば、
select * from emp,dept where emp.deptno=dept.deptno;
だと、下から上になります。

なお、ルールベースの場合、複数の索引がある場合に、どれを選択するか迷ったときも
何とも言えない索引選択をしてくれます。(^^; (どうも、索引名の昇順になる傾向)
    • good
    • 2

No.2です。

ちょっと、手元に資料がないのであいまいな回答になりますが。

他の方もおっしゃっていますが、現在のバージョンではコストベースとなっており今後はルールベースは廃止される方向です。
で、バージョンなどによりますが、FROM句は下から実行されることが多いです。そのため、軸になるTABLE(データ量が少ないTABLE)を下に書くのが基本とされていたと記憶しています。

しかしながらNO.3の方のとおり実行計画をみるのが一番ではあります。また、現在は、SQLの規格が国際的なやつに完全準拠(SQL98とかなんとか)し、JOIN句の使用を推奨していますので、今後はFROM句の記述順などはあまり有効にはならないとおもいます。

補足ですが、ヒントを使えばなるたけヒントに従います。(つまり実行順序を制御できる)しかしながら、「なるたけ」であって、Oracle君がやっぱこっちのほうがいいや!(コストベース)と判断すればそれまでです。

Oracleの方向性としては、今後こういった「チューニング」ということを極力なくす方向です。したがって、こういった知識も・・・話がそれました。

そういうわけで、要は「実行計画をある程度みよう。でもコストベースなんでOracle君次第だよ。だから統計情報は採ろうね!」とうい考え方でいいんではないでしょうか。
    • good
    • 0

WHEREでの条件判断の順番は、オラクルの都合で、順番が決まります。


記述した順番でも、その逆順でもありません。

一般的プログラム言語の場合、論理演算子と()での優先順位を考慮しつつ
書いた順番に評価していきますが、RDBの場合、WHEREに書かれた要素が
実行計画で、索引の使用する/しないに影響します。
そのため、評価の順番が状況次第で逐次変化します。


たとえば、
select * from emp where to_number(ename)=0 and empno=9999 and to_number(deptno)=0
としたとき、

ワザと数値変換できないフィールドを数値変換しているので、
上から評価しても、下から評価しても、エラーを返すべきですが、
真ん中の要素が、プライマリキーであるため、実行計画で、
索引検索すべしとされました。そのため、真ん中の要素を
一番最初に評価し、そのあと、他の条件を判断することに
なります。今回の場合、索引検索で0件となるので、その他の条件を
判断せず、終了する。(=エラーにはならない)
    • good
    • 3

まず答えとして、条件の実行順序ですが必ずしも記述した順番ではありません。



条件が適用される順番=データを取得してくる順序になりますが、同じSQL文でもOracleの設定(ルールベースかコストベースか)、データの状態、インデックスの有無、等々によって左右されるため、一概にこういう順番になりますということはありません。

これは、Oracleのオプティマイザという機能がSQL文を解析した後に、できるだけ速く結果を返すようにさまざまな情報からデータを取得する順番を決めるからです。(これを実行計画と呼びます。)
そのため、実際にどういう順番で取得してくるかはSQLの実行計画を確認してみないとわかりません。

>下から上だと思った根拠は、WHERE句に条件を2つ記述して、2つともにミスがあった場合、下の条件のミスに対してエラーメッセージが返ってきたためです。

とありますが、これはあくまで構文解析の順番になります。構文解析がOKになってから実行計画が作成され、実行計画を元にデータが取得されるので、エラーの発生順と実行順序は関係ないです。

実行計画について調べてみるとパフォーマンスを考慮したいいSQL文が書ける様になると思います。
    • good
    • 1

下から上というのはFROM句と勘違いされていると思います。

    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
やはりWHERE句は上から実行されるのですね。下からというのは私の思い違いだったんですね(^^;

FROM句の順序についても全く知らないのですが、FROM句では下から実行されるものなのでしょうか?
FROM句の実行というのが、いまひとつピンとこないのですが、
FROM (SELECT ○○ FROM ×× ・・・) AS TABLE1,
   (SELECT △△ FROM □□ ・・・) AS TABLE2
のように、FROM句の中にSELECT文を記述した場合に、下のTABLE2の方から先に実行されるということなのでしょうか?

FROM TABLE1,
   TABLE2
のように、SELECT文を記述しない場合には、実行順序は関係あるのでしょうか?(例えば、WHERE句の実行順序に関わってくるとか・・・)

ご教示いただければありがたいです。

お礼日時:2005/10/16 01:53

上からというか、「左から右へ」が原則です。


下から上というのは、どういう根拠なのでしょうか?

この回答への補足

ご回答ありがとうございます。
例えば、
 WHERE 会員番号 = 1234
 AND  性別 = '男'
と打ったとすると、
先に会員番号で絞り込んで、さらに性別で絞り込むのか、
それとも性別で絞込んだ後、会員番号で絞り込むのか、ということが知りたいんです。

SQLの記述にミス(列名の間違いや、データ型の不一致など)があった場合、エラーメッセージが帰ってきますよね。
下から上だと思った根拠は、WHERE句に条件を2つ記述して、2つともにミスがあった場合、下の条件のミスに対してエラーメッセージが返ってきたためです。

補足日時:2005/10/16 01:18
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q3つの表の外部結合

表A、B、Cの3つがあり、Aのすべての行を出力したいと考えています。
外部結合を用いるのだとは思うのですが、3つの表に対して行う場合の
書き方がわからず困っています。
ご教授いただけないでしょうか?
select * from a,b,c
where a.商品ID =b.商品ID (+) and b.商品ID (+) =c.商品ID (+)
としてみましたが、うまくいきませんでした。

Aベストアンサー

ansi構文の趣旨からいえば、結合条件と絞り込み条件は分けて書くので・・

select *
from a
left join b on (a.商品ID =b.商品ID)
left join c on (b.商品ID =c.商品ID)
where a.年月 = 任意の値

と書くのが一般的でしょうね。

QOracle(オラクル)で、日付時刻型の検索方法について

質問させていただきます。
データベースはオラクルを使っていて、
SQL文で、抽出するときにエラーが出て困っています。

日付時刻型が「2005/05/26 19:13:00」という感じで入ってます。
2005/05/26 を抽出したいのですが、
BETWEEN '2005/05/26 00:00:00' AND '2005/05/26 23:59:59'

だと、エラーでできません。
どなた様か、ご教授よろしくお願いしますm(_ _)m

Aベストアンサー

日付検索を行う場合は、以下のように書式を含める必要があります。

col BETWEEN TO_DATE('2005/05/26 00:00:00','YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2005/05/26 23:59:59','YYYY/MM/DD HH24:MI:SS')

ただ、厳密には

col >= TO_DATE('2005/05/26', 'YYYY/MM/DD')
AND
col < TO_DATE('2005/05/27', 'YYYY/MM/DD')

と書くべきでしょうね。

Q実行計画の「COST」と「BYTE」について教えていただきたいです。

実行計画の「COST」と「BYTE」について教えていただきたいです。

書籍には
COST・・・・CBOによって見積もられた操作コスト。
BYTE・・・・アクセスされるバイト数のCBOのアプローチによる見積もり。
と書かれていますが、いまいちピンときません。


私は、
COSTは、検索するテーブルのデータ量が多いほうがコスト値が大きくなる。
BYTEは、検索条件に合致して取得できるデータが多いほうがバイト値が大きくなる。
と思っているのですが、正しいでしょうか?

Aベストアンサー

このあたりを参考にしてください。
COSTはデータ量だけではなく、その表やViewのアクセスに要する時間やSortや結合が必要なら、そのために必要なCPU時間等も考慮されています。
表があるHDDのアクセス速度なんかも考慮されているし、表のエクステントが複数になっているかとかも考慮されています。
書籍はわかりにくいかもしれませんが、嘘は少ないと思います。著者が思い違いをしてないとは言い切れませんが。

参考URL:http://otn.oracle.co.jp/forum/message.jspa?messageID=35016743

QMAX値を条件にデータを取得するには?

SQL文で困っています。
ご教授下さい。


下記のようなデータがあった場合、それぞれの区分毎に
年月が最大(最新)のデータを取得したいです。
(実際には1レコードにその他項目があり、それらも取得します。)
<検索対象データ>
区分 年月   金額
-----------------------------
A   200412  600
A   200503  560
B   200311  600
B   200508  1000
B   200504  560
C   200508  400
C   200301  1100


<取得したいデータ>

区分 年月   金額
-----------------------------
A   200503  560
B   200508  1000
C   200508  400

よろしくお願いします。

Aベストアンサー

テーブル名をXXXとすると次のようなSQLでよいと思います。(最善の方法かどうかは自信がないですが)

select B.* from (select 区分, max(年月) as 年月 from XXX group by 区分) As A
inner join XXX as B on A.区分 = B.区分 and A.年月 = B.年月
order by B.区分

QSELECTで1件のみ取得するには?

こんにちわ。
いまORACLE9iを使用している者です。

ACCESSでは
SELECT TOP 1 項目名 FROM テーブル名
ORDER BY 項目名;
で並べ替えたデータ群のうち,先頭の1件だけを
取ることができますが,
ORACLEでそのような機能(SQL)はあるでしょうか?
教えてください。
よろしくお願いします。

Aベストアンサー

order by と rownum を併用する場合は注意が必要です。

[tbl01]
cola | colb
------------
1000 | aaaa
1001 | bbbb

というデータがある場合、
select cola from tbl01 where rownum < 1 order by cola desc;
とすると、「1001」ではなく、「1000」が返されます。
これは、order by の前に rownum < 1 が適用されてしまうからです。

解決するには、
select aaa from (select cola aaa from tbl01 order by cola desc) where rownum = 1;
とすれば良いです。

Q外部結合と等価結合のパフォーマンスの違いについて(ビューの場合)

Oracle10gでのSQL文の違いについて教えて下さい。

前回の質問は、ストアドプロシージャに記述
されていて、バッチとして動かしています。
と書きましたが、ビューの場合のパフォーマンスの違いは
どうなるのでしょうか?ビューの場合も同じような現象です。
下記の2つのSQL文は外部結合ありと外部結合なしの違いだけで、
他は変わりありません。
外部結合ありのほうは
結果がすぐに返されるのですが、外部結合なしのほうは
結果が返ってこない、あるいはかなり時間がかかるという
現象が起きています。
SQL文は簡略して記述していますが、SELECT句には、
TO_CHAR()やSUM(CASE WHEN ...THEN ...ELSE...)が使用してあり
少し重くなる処理も含まれています。
この2つのSQL文でパフォーマンスに影響している原因は
何なんでしょうか?オプティマイザとか実行計画とかの
説明を読んだのですが、いまいちよく解りません。。
自分では中級者以下だと思っていますので、わかりやすく
説明して頂けたら助かります。宜しくお願い致します。

(外部結合ありのSQL)
SELECT
 a.項目1,
 a.項目2,
 a.項目3,
 a.項目4,
 a.項目5
FROM
 TBL_A a,
 TBL_B b
WHERE
 a.項目1 = b.項目1(+) AND
 a.項目2 = b.項目2(+) AND
 a.項目3 = b.項目3(+) AND
 a.項目4 = b.項目4(+) AND
GROUP BY
 a.項目1,
 a.項目2,
 a.項目3,
 a.項目4,
 a.項目5

(外部結合なしのSQL)
SELECT
 a.項目1,
 a.項目2,
 a.項目3,
 a.項目4,
 a.項目5
FROM
 TBL_A a,
 TBL_B b
WHERE
 a.項目1 = b.項目1 AND
 a.項目2 = b.項目2 AND
 a.項目3 = b.項目3 AND
 a.項目4 = b.項目4 AND
GROUP BY
 a.項目1,
 a.項目2,
 a.項目3,
 a.項目4,
 a.項目5

Oracle10gでのSQL文の違いについて教えて下さい。

前回の質問は、ストアドプロシージャに記述
されていて、バッチとして動かしています。
と書きましたが、ビューの場合のパフォーマンスの違いは
どうなるのでしょうか?ビューの場合も同じような現象です。
下記の2つのSQL文は外部結合ありと外部結合なしの違いだけで、
他は変わりありません。
外部結合ありのほうは
結果がすぐに返されるのですが、外部結合なしのほうは
結果が返ってこない、あるいはかなり時間がかかるという
現象が起きています...続きを読む

Aベストアンサー

オラクルのオプティマイザは、テーブルの検索の方法を決めますが、外部結合と内部結合で
立案される実行計画に違いがあり、内部結合の方が合理的な検索方法を立案しているので
結果的に、内部結合の方が速いという話なんですが・・

実行計画を見なければ、判りませんが、
・外部結合はbに対して全表検索を選択した。
・内部結合では、bを索引検索を選択した。
・bの検索量が、bの格納件数のうち、ごく一部なので、全表検索と索引検索では、極端に検索時間が違う。
ということなんだと思います。(推測なので、実は違うかも知れません)

オラクルのマニュアルで、パフォーマンスチューニングガイドというマニュアルがあると思うので、
一読されることをお勧めします。


ちなみに、お書きになったSQLは何か変です。
内部結合のSQLは、bの項目を返さないので、実質的にbに存在するかのチェックを行っているに等しいものです。
書き方や流儀の問題で、内部結合が良いのか、exists条件が良いのか、in条件(メンバーシップ検査)が良いのか
変わってくると思いますが、一応理解できるものです。
しかし、外部結合のSQLについては、bを検索するけど、何もしない??理解に苦しむSQLになっています。
基本的に、内部結合より遅くなる外部結合を、わざわざ書いてみた、というように感じます。
(一般論ですが、同じ書き方をしたら、外部結合は内部結合と同等以下です)

オラクルのオプティマイザは、テーブルの検索の方法を決めますが、外部結合と内部結合で
立案される実行計画に違いがあり、内部結合の方が合理的な検索方法を立案しているので
結果的に、内部結合の方が速いという話なんですが・・

実行計画を見なければ、判りませんが、
・外部結合はbに対して全表検索を選択した。
・内部結合では、bを索引検索を選択した。
・bの検索量が、bの格納件数のうち、ごく一部なので、全表検索と索引検索では、極端に検索時間が違う。
ということなんだと思います。(推...続きを読む

QSQLで特定の項目の重複のみを排除した全項目を取得する方法

私は仕事上でデータベースを扱っていて、タイトルのような処理を行う必要があるのですが、いかんせん方法がわからずネット上を検索しても同様だったためここで質問させていただきます。

質問点を簡単に説明いたしますと、
たとえばAというテーブルがあって、

項目名1 項目名2 項目名3 項目名4
 A    あ    ア    亜
 A    い    ア    以
 A    う    ア    宇
 B    え    イ    江
 B    お    イ    尾

上のような構造になっている場合に「項目名1」について重複している項目を排除し、結果として


項目名1 項目名2 項目名3 項目名4
 A    あ    ア    亜
 B    え    イ    江

上のようなデータを取得したいのです。
この時に、Aの重複を排除して取得するレコードは1~3行目のどれでもよいです。
また、データを取得する際には必ずそのレコードの「全項目」を取得したいのでDistinctはうまく使えませんでした。

どなたか詳しい方、方法を教えてくださると幸いです。回答お待ちしております。

私は仕事上でデータベースを扱っていて、タイトルのような処理を行う必要があるのですが、いかんせん方法がわからずネット上を検索しても同様だったためここで質問させていただきます。

質問点を簡単に説明いたしますと、
たとえばAというテーブルがあって、

項目名1 項目名2 項目名3 項目名4
 A    あ    ア    亜
 A    い    ア    以
 A    う    ア    宇
 B    え    イ    江
 B    お    イ    尾

上のよ...続きを読む

Aベストアンサー

比較可能で一意性のある値をもてる項目6をテーブルに追加して、

select T.* from T, (select Item1,min(Item6) as Item6 from T group by item1) W where T.item6=W.item6;

――ってやるのが、一番手っ取り早いと思います。
他のところに影響がでないのであればですが。
oracleならrowidを使うとか、レコードの更新時刻を突っ込むとか。

Qsqlplusで表示が変なので、出力を整形したい。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------

上記のように意味不明な形式で出てきます。

例えばこんな風に

select カラム1,カラム2,カラム3 from hoge;

カラム1 1の値
---------------------------
カラム2 2の値
---------------------------
カラム3 3の値

等のように分かりやすく表示できないでしょうか?

ちなみにOracle9iR2を使用しています。
sqlに関するツールは使用できないルールでして、あくまでsqlplusのコマンド上でみやすくしなければなりません。

分かりづらくですいませんが、皆さま、ご教授お願いします。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
-----------------------...続きを読む

Aベストアンサー

SQLPLUSを起動して、

SQL>set linesize 列数

でどうだ。

SQL>show linesize

で確認ができる。

Qcount(1)とcount(*)の違い

初心者です。
以下のSQL文の違い及びcount(1)の1が何を表しているのか
教えて頂けないでしょうか?

select count(*) from table
select count(1) from table

また、参考しやすいサイト等ありましたら教えて頂けないでしょうか?

Aベストアンサー

COUNT(*)はNULLを含む件数
COUNT(expr)とCOUNT(ALL expr)はexpr列のNULLが含まない件数
COUNT(DISTINCT expr) expr列の種類(null以外)
です。
たまにcount(1)の記述を確かに見受けます。
これは「select 1 from <TABLE名>」でカウントした結果と同じです。
(つまり、count(*)と同じ件数になるはず)
#ためしにCOUNT(DISTINCT 1)とかすると1になるはずです
#1番目の列ではないはず

QViewにインデックスは張れますか?

件名の通りなのですが、作成したViewが遅くて困っています。
改善方法としてはViewを作成しないで従来のSQLにインデックスを張って取得する方法にしようかなと考えています。
なにかいい方法はありますか?

Aベストアンサー

Viewの元テーブルに適切なIndexを貼る、ではいけないのですか?


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング