PostgreSQL で order by 2 と書くと2番目に指定したカラムでソートできる

タイトルの通り。PostgreSQL において SELECT 文で order by 2 を指定すると、2番目に指定したカラムでソートをすることができる。

試してみる

過去の記事でも利用した、都道府県コード(id)とローマ字表記(name)のテーブルで試してみる。 order by 2 を指定すると、2番目に指定されているローマ字表記(name)の順にソートされていることが分かる。

postgres=# select * from prefecture order by 2 limit 10;
 id |   name    
----+-----------
 23 | Aichi
  5 | Akita
  2 | Aomori
 12 | Chiba
 38 | Ehime
 18 | Fukui
 40 | Fukuoka
  7 | Fukushima
 21 | Gifu
 10 | Gunma
(10 rows)

当然ではあるが、指定したカラム位置に該当するものがない場合はエラーになる。

postgres=# select * from prefecture order by 3 limit 10;
ERROR:  ORDER BY position 3 is not in select list
LINE 1: select * from prefecture order by 3 limit 10;

これだけだとカラム名を指定した場合と変わらないが、例えば集約関数などを用いて計算した結果でソートしたい場合などに、AS で出力列名を指定せずにソートすることができる。 また、カラム位置を複数指定してその順でソートすることもできる。

postgres=# select *, length(name) from prefecture order by 3 limit 10;
 id | name  | length 
----+-------+--------
 24 | Mie   |      3
 41 | Saga  |      4
 21 | Gifu  |      4
 44 | Oita  |      4
 29 | Nara  |      4
 10 | Gunma |      5
 39 | Kochi |      5
 18 | Fukui |      5
 25 | Shiga |      5
  5 | Akita |      5
(10 rows)

postgres=# select *, length(name) from prefecture order by 3, 2 limit 10;
 id | name  | length 
----+-------+--------
 24 | Mie   |      3
 21 | Gifu  |      4
 29 | Nara  |      4
 44 | Oita  |      4
 41 | Saga  |      4
 23 | Aichi |      5
  5 | Akita |      5
 12 | Chiba |      5
 38 | Ehime |      5
 18 | Fukui |      5
(10 rows)

PostgreSQL文書( 7.5. 行の並べ替え(ORDER BY) )を見てみると以下のような記載がある。

sort_expressionは以下のように列ラベルもしくは出力列の番号で指定することができます。

DBMSのドキュメントも見てみる

PostgreSQL 以外の DBMS のドキュメントも見てみると、OracleMySQL でも同様の構文で同様の操作ができるとの記述がある。

ただし、MySQLのドキュメントには「カラム位置の使用は、この構文が SQL 標準から削除されたため非推奨です。」との記述がある。

標準SQLの仕様を見てみる

SQLANSI(米国国家規格教会)、現在は ISO(国際標準化機構) によって言語仕様の標準化が行われており、標準 SQL 規格として制定されている。 1986年に初版である SQL86 が制定されて以降、不定期ではあるが更新がなされており、2023年5月現在の最新版は SQL:2016 である。

標準 SQL 規格の内容を確認するためには、基本的にドキュメントを購入する必要がある。 規格検索結果 | 日本規格協会 JSA Group Webdesk で検索してみると、個人で購入するには価格がかなり高めであり、さらに分冊になっていることから全て揃えるのは難しいような印象を受ける。

文法レベルでの確認をしたいだけであれば、有志により公開されている SQL overview で確認すればほとんど事足りるのではないかと思う。

jakewheat.github.io

話を order by 2 に戻すと、SQL92 では order by の sort key として unsigned integer が指定可能になっている。

しかし、次の版である SQL:1999 からは記述が削除されている。この版から、標準 SQL ではカラム位置の指定は仕様の対象外になったものと思われる。

今回ドキュメントを確認した PostgrSQL/MySQL/Oracle はいずれも 1999年以前から存在している DBMS であり、作成済みの SQL の互換性を維持するために独自に構文をサポートしているという可能性は十分に考えられるのではないかと思う。

まとめ

PostgreSQL だけでなく、OracleMySQL でも order by 2 を指定することで、2番目に指定したカラムでソートをすることができる。 ただし、標準SQLで定められた記法ではなく、DBMSによっては非推奨とされているため、利用できるかどうかはドキュメント等で確認しておくのが良さそうである。

個人的な感想として、一見しただけでは処理内容が分かりにくいことから利用する機会が少なそうに感じていたが、集約関数などと組み合わせる時に別名を指定してなくて良いなどのメリットはありそうだということが分かった。ただ、読み手としてはカラム名をつけてもらえる方が分かりやすいかとは思うので、利用できるかどうかと合わせて場合に応じて使うのが良さそうである。