物流・倉庫・WMS・プログラマ日記

物流・倉庫・WMS・プログラマ日記

在庫管理・倉庫管理を扱う事が多いプログラマの備忘録です。

【SQLを丁寧に理解する】ROWNUM と ORDER BY ~PART2:SQLの実行順序~

こんにちは、EightyEightRiceです。

 

今日の記事は、【SQLを丁寧に理解する】ROWNUM と ORDER BY ~PART2:SQLの実行順序~  です。

データベースを扱い場合に、よくハマってしまう項目について、丁寧に説明していきます。

ざっと読み飛ばすだけでも、

「へぇーそうなんだ」

と、思っていただけるような構成を心がけています。

 

今回は

ROWNUM と ORDER BY ~PART2:SQLの実行順序~

です。

こんな話を聞いた事はありませんか?

「ROWNUMとORDER BY を一緒に使ってはいけない」

 

結論は、「ROWNUMとORDER BYは、一緒に使って良い場合と悪い場合がある」です。

あるSQLの結果に対して、

ORDER BY でソートして、WHERE句で「ROWNUM = 1」のような使い方

は、かなり危険です。 

しっかりと理解する為に、以下の2つのポイントに分けて解説していきます。

・ROWNUMとは

SQLの実行順序

 

前回(PART1)では、ROWNUMについて解説しました。

今回はSQLの実行順序と、なぜ 

”「ROWNUM = 1」のような使い方は、かなり危険”

なのか解説します。

 

実行順序について、今回は特にSELECT文について考えます。

基本的な句として、まず、

SELECT、FROM、WHEREがあります。つぎにオプション的な句として、

JOIN、GROUP BY 、ORDER BY 、HAVING などがあります。

 

これらの句は実行される順序が決まっています。

(あるSQLはSELECTから実行、またあるSQLはFROM句から実行とはなりません。)

 

SELECT文の句は以下の順序で実行されます。

1. FROM
2. JOIN
3. WHERE
4. GROUP BY
5. HAVING
6. SELECT
7. ORDER BY

※今回の記事に影響のない句(ONやLIMIT、DISTINCTなど)は省略しています

 

この実行順序をもとに以下のSELECT文の動作を考えてみます。

 

SELECT

    社員コード

  , 生年月日

  , ROWNUM

FRON

  社員表

WHERE

  ROWNUM = 1

ORDER BY

  生年月日

 

生年月日の昇順に並べて、一番若い社員をSELECTしようとしています。

ただ、これが危険なSQLです。

なぜでしょうか。

ROWNUMは、FROMとWHEREから抽出された行に対して1から重複しない連番を付番します。

WHERE句にROWNUM = 1 とすると、結果的に1行目の行が抽出されます。

一見正しい結果が得られそうですが、ここで注意したいのは、ORDER BY の実行順序が最後になっている点です。

 

サンプルのSELECT文のように、  

WHERE

  ROWNUM = 1

ORDER BY

  生年月日

とすると、1行抽出した後に、生年月日でソートになってしまいます。

 

WHERE句で絞られたデータを取り出す順にROWNUMが付番されるますが、

取り出す順序はデータベースエンジンに依存するので、どの行から抽出されるかはわかりません。

1番若い社員を抽出するには不適切なSQLの使い方と言えます。

 

今回解説したポイント

ORDER BY でソートして、WHERE句で「ROWNUM = 1」の注意点

「単純に条件を満たすデータを1件抽出する場合」

➡ OK

「ある列を指定して並べ替えたものから最小(最大)のデータを抽出する場合」

➡ NG

 

以上、解説でした。

 

/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_

SQLについて質問があれば随時募集しています。

ご遠慮なくお問い合わせください.

/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_