仕事中で詰まったので調べた。結構、ありがちな処理なんだけど初めて知ったので、情報共有のためにエントリーにしておく。
MySQLで出力される結果を並び替える場合は「order by」を使うんだけど、これはascとdescで昇順と降順の並び替えしかできない。
例えば、給料の日割りと額で並び替えたいって場合は条件を複数並べればいい。
No | 日割り | 金額 |
---|---|---|
1 | 月給 | 180000 |
2 | 時給 | 850 |
3 | 日給 | 8000 |
4 | 月給 | 150000 |
上記のテーブルがあるときならば下記になる。
select * from 給与明細 order by 日割り desc, 金額 desc;
No | 日割り | 金額 |
---|---|---|
1 | 月給 | 180000 |
4 | 月給 | 150000 |
3 | 日給 | 8000 |
2 | 時給 | 850 |
ちなみにorder byはint型のような数値にかぎらずvarchar型でもソートできる。日本語でも大丈夫。詳細はこちらでも参照してください。
で、本題なんだけど上記のテーブルで日割りをソートするときに、必ず日給を一番上に来るようにソートするにはどうすれば良いと思う?これ、結構悩んで詰まった。
こういう場合はCase文を使えば良いんである。
CASE
WHEN 条件1 THEN 処理
WHEN 条件2 THEN 処理
WHEN 条件3 THEN 処理
…
ELSE 処理
END
select * from 給与明細 order by case when (日割り = '日給') then 100 else 0 end desc, 日割り desc, 金額 desc;
No | 日割り | 金額 |
---|---|---|
3 | 日給 | 8000 |
1 | 月給 | 180000 |
4 | 月給 | 150000 |
2 | 時給 | 850 |
MySQL:CASEを使ってレコードをソート(ORDER BY) | エンジニア足立のコーディング日記 - 株式会社ディープ
このSQL文では最初に日割りで日給に当てはまる行に100というパラメータを割り振ってそれ以外には0を割り振る。そしてorder byで並び替えた上で、他の行の並び替えをしている。order byにCase文を使うと条件を指定した柔軟な並び替えが可能になる。
Case文は他にもいろんなことに使える。例えば、県コードは、1:北海道、2:青森、・・・・・・ 47:沖縄というように振られているが、これを東北、関東、九州といった地方単位にまとめて、その単位で人口を集計したい、という場合。
通常ならば新しく地方コードのカラムを追加しなければならないんだけど、テーブルが冗長になる。これをSQL側で対応することができる。
SELECT SUM(popularity), CASE pre_name WHEN '徳島県' THEN '四国' WHEN '香川県' THEN '四国' WHEN '愛媛県' THEN '四国' WHEN '高知県' THEN '四国' WHEN '福岡県' THEN '九州' WHEN '佐賀県' THEN '九州' WHEN '長崎県' THEN '九州' WHEN '熊本県' THEN '九州' WHEN '大分県' THEN '九州' ELSE 'その他' END FROM Table_A GROUP BY CASE pre_name WHEN '徳島県' THEN '四国' WHEN '香川県' THEN '四国' WHEN '愛媛県' THEN '四国' WHEN '高知県' THEN '四国' WHEN '福岡県' THEN '九州' WHEN '佐賀県' THEN '九州' WHEN '長崎県' THEN '九州' WHEN '熊本県' THEN '九州' WHEN '大分県' THEN '九州' ELSE 'その他' END;
データの複雑な並び替えや変更を行わないといけないけど、データベースの構造には触れたくないシーンはありがちだ。そういう時にはCase文を使えばなんとかなるかもしれない。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.6.5.1 CASE 構文