別に Oracle 独特な話ではないですが…
某 SNS で 「Order By 句に Select 文が書けるのか?」という話題があったので調査。
結論としては「書ける」
たとえば以下のようなコードが書けます。
select * from EMP a
order by (
select b.ENAME from EMP b
where a.EMPNO = b.EMPNO -- EMPNO は Primary Key
);
で、これは普通に書くと、以下と同じ意味です。
select * from EMP
order by ENAME
ENAME 列でソートってことですね。
なぜ同じになるかというと、Order by 句で指定するものが、実は "列名" ではなく、"列のデータそのもの" だから。
要するに、Order by の "ENAME" は 実質的に "select ENAME from EMP" と同じ。
もっとも、直接 Order by に "select ENAME from EMP" を書くと直積になってしまうので、where 句で絞っています。
(直積以前に戻すデータはスカラーでないとダメですが)
なので、"order by 列名" は "order by (Select ~)" の糖衣構文だと思ったほうがよいかもしれません。
なぜならば、繰り返しになるけど Order by で渡っているものは、列名ではなく、ましてカラム番号でもなく、列のデータそのものだからです。
だからたとえば以下のような記述をすると、EMPNo の末尾1桁でソート、とかができる。
select * from EMP a
order by (
select mod(EMPNO,10) -- 末尾1桁
from EMP b
where a.EMPNO = b.EMPNO
);
結果 (EMPNO の末尾1桁でソートされる)
EMPNO ENAME --------- ------------ 7900 JAMES 7521 WARD 7782 CLARK 7902 FORD 7934 MILLER 7654 MARTIN 7844 TURNER 7566 JONES 7876 ADAMS 7698 BLAKE 7788 SCOTT
また、以下のような書き方もできたりします。
要するに、列名だろうと select だろうとなんだろうと、ソート対象になり得る列を生み出せればよいということですね。
select * from DEPT order by ( case DEPTNO when 20 then 1 when 10 then 2 when 40 then 3 when 30 then 4 end );
結果 (then ? の ? 順でソートされる)
DEPTNO DNAME ------- ------------------ 20 RESEARCH 10 ACCOUNTING 40 OPERATIONS 30 SALES
もっとも、こんな書き方しなくても…というのは多分ごもっともな気がするので、多用するのは禁物かもしれません(汗
p.s.
ところで当初、"order by (select n …"、の n がカラム番号なのかな?とか思って、
select * from EMP order by (select 2 from DUAL);
とか書いてテストしてみましたが…
エラーにこそならないものの 2 列目でソートされないし、それどころかソートされている列が見当たらない…
あたりまえですね。これだと、全行が "2" の列を作って、その列をソートして出力しようとしているだけなので、ソートされるわけがありませんよ…(汗 # もちろんエラーにもなりませんね_| ̄|○
[Oracle] 相関サブクエリー | オールトの雲
[...] [Oracle] Order by 句に Select 文 [...]
Link | 2013年8月6日 23:01