ORDER BY で CASE文を使って特定の行を上位に表示する

CentOS 6.x の PostgreSQL 8.4 と SQLite3 で動作確認。

何らかのデータをソートして表示する際、特定の行だけは上位に表示したい事がある。

例えば、国マスタをコード順でソートした時に、日本を一番上に表示し、他はコードでソートして表示したい、等々。


単純にコードでソートした場合の例

db=> SELECT * FROM country ORDER BY iso;
  iso   |                    name
--------+--------------------------------------------
 AD     | アンドラ
 AE     | アラブ首長国連邦
 AF     | アフガニスタン
 AG     | アンティグア・バーブーダ
 AI     | アンギラ
 AL     | アルバニア
 AM     | アルメニア
 AN     | オランダ領アンティル
 AO     | アンゴラ
 AQ     | 南極


ORDER BY にCASE文を使った場合の例

db=> SELECT * FROM country ORDER BY CASE iso WHEN 'JP' THEN 1 ELSE 2 END, iso;
  iso   |                    name
--------+--------------------------------------------
 JP     | 日本
 AL     | アルバニア
 DZ     | アルジェリア
 AS     | サモア
 AD     | アンドラ
 AO     | アンゴラ
 AI     | アンギラ
 AQ     | 南極
 AG     | アンティグア・バーブーダ
 AR     | アルゼンチン
 AM     | アルメニア
 AW     | アルバ


注意点は、下記のように、ORDER BY の条件でCASE文だけにすると、ELSE部分のソートが意図した通りにならない事がある。
CASE文だけでなく、本来ソートしたかった条件も必要。

失敗な例

db=> SELECT * FROM country ORDER BY CASE iso WHEN 'JP' THEN 1 ELSE 2 END;
iso    name
-----  ---------------------------------
JP     日本
AF     アフガニスタン
AL     アルバニア
DZ     アルジェリア
AS     サモア
AD     アンドラ
AO     アンゴラ
AI     アンギラ
AQ     南極


同様に、都道府県の場合の例(東京都を一番上に表示、他はコードでソート)

db=> SELECT * FROM pref ORDER BY CASE cd WHEN 13 THEN 1 ELSE 2 END, cd;
 cd |   name
----+----------
 13 | 東京都
  1 | 北海道
  2 | 青森県
  3 | 岩手県
  4 | 宮城県
  5 | 秋田県
  6 | 山形県
  7 | 福島県
  8 | 茨城県
  9 | 栃木県


国のデータは以下を利用。
国名と国コードの対応表