SQL ORACLEのROWNUMで行番号を取得する際の注意点
Oracleで行番号を取得する際の基本的な考え方と注意点を紹介します。
行番号はROWNUM
で取得することができます。注意しなければならないのは、ORDER BY
でソートする場合です。ORDER BY
はSELECT句でROWNUM
を採番した後に行われるため、例えば下記のようなSQL
を実行した場合、行番号も含めてソートされてしまいます。
SELECT
ROWNUM 行番号
,T1.社員コード
,T1.社員名
FROM
社員マスタ T1
ORDER BY T1.社員コード
行番号 | 社員コード | 社員名 |
---|---|---|
5 | 1 | テスト社員1 |
33 | 2 | テスト社員2 |
672 | 3 | テスト社員3 |
17 | 4 | テスト社員4 |
14 | 5 | テスト社員5 |
なので、社員コードでソートして上位5件を取得したい場合、下記のようなSQLでは正しく取得することができません。
SELECT
ROWNUM 行番号
,T1.社員コード
,T1.社員名
FROM
社員マスタ T1
WHERE
ROWNUM BETWEEN 1 AND 5
ORDER BY T1.社員コード
行番号 | 社員コード | 社員名 |
---|---|---|
5 | 1 | テスト社員1 |
1 | 24 | テスト社員24 |
2 | 243 | テスト社員243 |
4 | 467 | テスト社員467 |
3 | 589 | テスト社員589 |
なぜなら、WHERE
句で指定しているROWNUM
はORDER BY
でソートする前の行番号だからです。
社員コードでソートして取得したデータに対して1行目から行番号を振りたい場合は、下記のように副問い合わせを利用します。
そしてその行番号に対してWHERE
句で条件を指定すれば、上位10件を正しく取得することができます。
SELECT
ROWNUM 行番号
,T1.社員コード
,T1.社員名
FROM (
SELECT
T1.社員コード
,T1.社員名
FROM
社員マスタ T1
ORDER BY T1.社員コード
) T1
WHERE
ROWNUM BETWEEN 1 AND 5
行番号 | 社員コード | 社員名 |
---|---|---|
1 | 1 | テスト社員1 |
2 | 2 | テスト社員2 |
3 | 3 | テスト社員3 |
4 | 4 | テスト社員4 |
5 | 5 | テスト社員5 |
しかし、まだ問題があります。ページング処理などで6件~10件のデータを取得したい場合、WHERE ROWNUM BETWEEN 6 AND 10
としても正しく取得することができません。
WHERE句にROWNUM
の条件を指定して絞り込むと、SELECT句で採番したROWNUM
がまた変わって、そうするとWHERE句のROWNUM
で絞り込むデータも変わって...といった感じで、正しく取得することができません。(この理由は個人的な勝手なイメージです。正しく取得できないちゃんとした理由はありますが、難しくて混乱してしまうのでここでは説明しません。)
正しく取得するためにはさらに副問い合わせをして、採番した行番号に対してWHERE
句で絞り込みを行うようにします。
SELECT
T1.行番号
,T1.社員コード
,T1.社員名
FROM (
SELECT
ROWNUM 行番号
T1.社員コード
,T1.社員名
FROM (
SELECT
T1.社員コード
,T1.社員名
FROM
社員マスタ T1
ORDER BY T1.社員コード
) T1
) T1
WHERE
T1.行番号 BETWEEN 6 AND 10
行番号 | 社員コード | 社員名 |
---|---|---|
6 | 6 | テスト社員6 |
7 | 7 | テスト社員7 |
8 | 8 | テスト社員8 |
9 | 9 | テスト社員9 |
10 | 10 | テスト社員10 |
何階層も副問い合わせを実行すると、処理が複雑になってしまいます。ROWNUM
ではなくROW_NUMBER()
を使えば副問い合わせをせずに、ソートしたあとの行番号を取得することができます。
SELECT
T1.行番号
,T1.社員コード
,T1.社員名
FROM (
SELECT
ROW_NUMBER() OVER(ORDER BY T1.社員コード) 行番号
,T1.社員コード
,T1.社員名
FROM
社員マスタ T1
) T1
WHERE
T1.行番号 BETWEEN 6 AND 10
ORDER BY T1.行番号
集計関数(SUM,COUNT,MAXなど)にOVER(...)つけて、分析関数として、効率よくデータを集計することができます。
SQL OVER句の分析関数で効率よくデータを集計するで分析関数の基本的な使い方を紹介します。