L
o
a
d
i
n
g
.
.
.

ホーム

お知らせ

製品・ソリューション

サービス

導入事例・パートナー

EXEM Academy・ブログ

会社情報

採用情報

2022.12.21

SQLチューニング(第41回)「ROWNUMの理解と関連SQL性能問題の理解」(1/6回)

今回から6回シリーズで、「ROWNUMの理解と関連SQL性能問題の理解」と題して、情報をお届けします。それでは、早速始めましょう。


 ROWNUMはOracleで提供する仮想カラムで、Select節で使う場合には抽出するデータの順番を付与する用途で使われ、Where節に使う場合には抽出するデータのうち一部データだけ持ってくる用途で使われます。 特にWhere節に使われるROWNUMはインデックスの特性を利用して、部分範囲処理に誘導でき、うまく使えば効率的なSQLになります。

 ROWNUMが1回の順番を付与することと、SQLを解釈するときにROWNUMの使用位置とSQLのコンポーネントとの関係を理解すれば、ROWNUMをより効率的に使用することができるでしょう。

 これから、基本的なROWNUMに対する内容を調べていきましょう。

12.1 ROWNUMデータを先に抽出した後、問い合わせよう

 ROWNUM_T1テーブルには下記のように合計10件のデータがあります。

C1    C2         C3
----- --  ---------
    1 C        101
    2 D        102
    3 E        103
    4 F        104
    5 G        105
    6 H        106
    7 I        107
    8 J        108
    9 K        109
   10 L        110

 10件のデータに対して下記のようにSQLを実行してみましょう。

テーブル12-1. ROWNUMのデータ抽出

SQL[1]SQL[2]
SELECT * 
  FROM (SELECT * 
           FROM t1 
        ORDER BY c1)
 WHERE ROWNUM >= 1 
   AND ROWNUM <= 5;
C1   C2   C3
—   — —-
  1   C   101
  2   D   102
3   E   103
4   F   104
  5   G   105
SELECT * 
  FROM (SELECT * 
           FROM t1 
       ORDER BY c1)
 WHERE ROWNUM >= 6 
 AND ROWNUM <= 10;
no rows selected

SQL[1]とSQL[2]はそれぞれの条件に合うデータが抽出されなければならないと予想されました。 しかしSQL[1]は1 ~ 5まで合計5件のデータが抽出されましたが、SQL[2]は何のデータも抽出されませんでした。

このような結果が導き出された理由は何なのでしょうか?

解答はROWNUMの特性で探してみることで得ることができます。 ROWNUMはSQL結果セットに順番を付与する仮想カラムで、Fetch段階で抽出する最初の行に1を付与します。 そして次の行が抽出されるたびにROWNUMの値を次々と増加させます。 ところで1が存在しないならば、次の順番を付与できないので何のデータも抽出されません。

すなわち、ROWNUMを利用して、ただ一件(ROWNUM=1)のデータだけ抽出したり、1から始めて順にN件のデータを抽出するのは可能ですが、ROWNUMの開始を1でない値から抽出しようとする場合にはデータが抽出されません。

ROWNUMの使用を誤った事例

WHERE ROWNUM = N ( N > 1 )
WHERE ROWNUM > N ( N > 1 )

 それならSQL[2]が本来の作成意図のとおりデータを抽出できる方法はないのでしょうか?

 ROWNUMが6 ~ 10のデータ(C1値が6 ~ 10)を抽出するためには、次のSQLのように先に抽出対象データにROWNUMを1から順番を付けた後ROWNUMが6 ~ 10までのデータを抽出すれば良いのです。

SELECT c1, c2, c3, RNUM
  FROM (
        SELECT ROWNUM rnum,
                 t1.*
          FROM (SELECT * FROM t1 ORDER BY c1) T1
)
WHERE rnum >= 6 and rnum <= 10 ;

   C1 C2         C3
----- -- ----------
    6 H        106
    7 I        107
    8 J        108
    9 K        109
   10 L        110

 いかがでしたでしょうか?次回は、「ORDER BYとROWNUMを同じ位置に置くのをやめよう」という内容でお送りします。ご期待ください。では、See You ^^


PHP Code Snippets Powered By : XYZScripts.com