みんなが頭を悩ます「ORDER BY句」の問題
まずは、データ最新の書式や研修の表示順について、確認しましょう。ORDER BY
句を指定しない場合の表示順は、何順ですか? 「Oracleがデータを取り出した順」ですよね。だから、どんな順に出てくるか、保証されるものではありません。だから、ORDER BY
句をつけて、昇順(小さい順)、降順(大きい順)に並べ替えて表示するのですよね。
それでは、昇順に並べた場合、NULL
は先頭に表示されますか? 最後ですか? 降順に並べた場合は?
SQL> SELECT empno,ename,mgr 2 FROM emp 3 WHERE deptno = 10 4 ORDER BY mgr; EMPNO ENAME MGR ---------- ---------- ---------- 7934 MILLER 7782 7782 CLARK 7839 7839 KING
例1が示すとおり、昇順に並べた場合、NULL
は最後(降順に並べた場合は先頭) に表示されます。 しかし、Oracleの仕様がそうであったとしても、みなさんの業務においては、昇順だろうが降順だろうが、NULL
を常に先頭に表示したいという要望があるかもしれません。さあ、そういう場合は、どうすればよいのでしょうか。
問1
上司(mgr)が設定されていない従業員を常にリストの先頭に出力する必要があります。どのSQL文を使用しますか。3つ選びなさい。
-
a. SELECT empno,ename,mgr
FROM emp
WHERE deptno = 10
ORDER BY mgr DESC; -
b. SELECT empno,ename,mgr
FROM emp
WHERE deptno = 10<br/ ORDER BY mgr NULLS FIRST; -
c. SELECT empno,ename,mgr
FROM emp
WHERE deptno = 10
ORDER BY mgr DESC NULLS FIRST; -
d. SELECT empno,ename,mgr
FROM emp<br/ WHERE deptno = 10
ORDER BY mgr DESC NULLS REVERSE; -
e. SELECT empno,ename,mgr
FROM emp
WHERE deptno = 10
ORDER BY mgr ASC NULLS LAST;
正解は、次の実行例のとおり、a、b、cです。
SQL> -- a SQL> SELECT empno,ename,mgr 2 FROM emp 3 WHERE deptno = 10 4 ORDER BY mgr DESC; EMPNO ENAME MGR ---------- ---------- ---------- 7839 KING 7782 CLARK 7839 7934 MILLER 7782 SQL> -- b SQL> SELECT empno,ename,mgr 2 FROM emp 3 WHERE deptno = 10 4 ORDER BY mgr NULLS FIRST; EMPNO ENAME MGR ---------- ---------- ---------- 7839 KING 7934 MILLER 7782 7782 CLARK 7839 SQL> -- c SQL> SELECT empno,ename,mgr 2 FROM emp 3 WHERE deptno = 10 4 ORDER BY mgr DESC NULLS FIRST; EMPNO ENAME MGR ---------- ---------- ---------- 7839 KING 7782 CLARK 7839 7934 MILLER 7782 SQL> -- d SQL> SELECT empno,ename,mgr 2 FROM emp 3 WHERE deptno = 10 4 ORDER BY mgr DESC NULLS REVERSE; ORDER BY mgr DESC NULLS REVERSE * 行4でエラーが発生しました。: ORA-00905: キーワードがありません。 SQL> -- e SQL> SELECT empno,ename,mgr 2 FROM emp 3 WHERE deptno = 10 4 ORDER BY mgr ASC NULLS LAST; EMPNO ENAME MGR ---------- ---------- ---------- 7934 MILLER 7782 7782 CLARK 7839 7839 KING
ORDER BY
句には、もう1つ便利な機能があります。 指定した件数分表示する機能です。
問2
emp表の中で給与が高い順に表示します。ただし、表示する行は3件のみとします。 どのSQL文を使用しますか。
-
a. SELECT ename,sal FROM emp
WHERE ROWNUM <= 3
ORDER BY sal DESC; -
b. SELECT ename,sal FROM emp
ORDER BY sal DESC FETCH FIRST 3 ROWS ONLY; -
c. SELECT ename,sal FROM emp
ORDER BY sal DESC FETCH FIRST 3 ROWS WITH TIES; -
d.SELECT ename,sal FROM emp
ORDER BY sal ASC FETCH LAST 3 ROWS ONLY;
正解は、次の実行例のとおり、bです。
SQL> -- a SQL> SELECT ename,sal FROM emp 2 WHERE ROWNUM <= 3 3 ORDER BY sal DESC; ENAME SAL ---------- ---------- ALLEN 1600 WARD 1250 SMITH 800 SQL> -- b SQL> SELECT ename,sal FROM emp 2 ORDER BY sal DESC FETCH FIRST 3 ROWS ONLY; ENAME SAL ---------- ---------- KING 5000 MILLER 4900 SCOTT 3000 SQL> -- c SQL> SELECT ename,sal FROM emp 2 ORDER BY sal DESC FETCH FIRST 3 ROWS WITH TIES; ENAME SAL ---------- ---------- KING 5000 MILLER 4900 SCOTT 3000 FORD 3000 SQL> -- d SQL> SELECT ename,sal FROM emp 2 ORDER BY sal ASC FETCH LAST 3 ROWS ONLY; ORDER BY sal ASC FETCH LAST 3 ROWS ONLY * 行2でエラーが発生しました。: ORA-00905: キーワードがありません。
FETCH FIRST
キーワードを使用して、戻される行の数または割合を指定できます。 ただし、FETCH LAST
というキーワードは存在しないので、ご注意ください。
件数を表示するときにはROWS
、割合のときはPERCENT
を使用します。今回は3件と指定があったので、3 ROWS
です。10%と指定された場合は、10 PERCENT
と書きます。
実行例からわかるように、給与の多い順に並べると3番目の金額は、実は3000
なのですが、同じ金額の人が2人います。順位的に表現すると、同額3位ってことですね。
しかし、設問では「3件のみ」と要求されていたので、ONLY
を使用します。「行制限している最後の行」と同じ値が連続していて、その行も表示する場合はWITH TIES
を使用します。
あ、aを選択したあなた。Oracle経験が長いですね。 OracleがFETCH FIRST
キーワードをサポートするまでは、ROWNUM
疑似列を使用して、限定何件を表示するというSQL文を(副問合せなどを駆使して)書くこともありました。私にも経験あります(苦笑)。 しかし、もうそんなことをする必要はないのです。おぼえておきましょうね。
ちなみに、5件スキップして、6件目から3件表示するということができるOFFSET
というキーワードもありますから、復習しておいてください。
もし、資格を取得済みの先輩方が、後輩指導のためにと思ってこの連載を読んでくださっているのなら、SQLとはいえ、最新の書籍や研修で知識/技術を身につけるよう指導してあげてください。 今まで苦労していたことが、キーワード1つで簡単にできるようになっているかもしれません。