たとえばこんなテーブル構成&レコードを考えます。
id
, name
, age
このレコード、age
がnull
のレコード(年齢情報が未入力の場合とでも考えてください)は常に先頭にして取得したい場合、どのようなSQLを書けばいいでしょうか。
※このテーブルはただの例です。「年齢は毎年変わるからDBのレコードに含めるのは適切じゃないぞ」というツッコミはよそでやってください。
何も考えずに書くとどうなる?
SELECT * FROM users ORDER BY age;
この挙動はRDBMS依存です。たとえばMySQLやSQL
Serverでは希望通りnull
レコードが先頭に来ますが、PostgreSQLやOracleでは最後に来るようです(実際に試したわけではなく検索して出てきた情報ですが)。
SQL:2003でのやり方
以下の構文が標準SQL(SQL:2003)で登場しました。
SELECT * FROM users ORDER BY age NULLS FIRST;
NULLS FIRST
をNULLS LAST
にすると、nullレコードが最後に来ます。ただしこの書き方は、MySQLなどの一部のRDBMSでは現時点でもサポートされていません。
移植性の高いやり方
NULLS FIRSTよりも移植性の高い書き方は以下の通り。
SELECT * FROM users ORDER BY (age IS NULL) DESC, age;
age
でソートする前にage IS NULL
の降順でソートすることで、age
がnull
のレコードだけが先頭に集まります。null
のレコードを最後に集めたい場合は(age IS NULL ASC)
でOK。基本的な構文しか使っていないので、MySQLでも動きます。
この書き方を自力で思いついたときは「おー、やったぁ!( `・ω・´)」という感じでかなり興奮したんですが、後で調べてみたら割と有名なイディオムらしくて( ´・ω・`)となりました。
応用編
この書き方は意外と応用が広く、null
を固定する以外にも色々な使い方ができます。
id=1のレコードだけ固定
例えば、「age
でソートするけどid
が1のレコードを先頭に固定したい」場合。id
がのユーザーは特殊なユーザーなので、年齢でソートする場合もこのユーザーだけは先頭にしたい・・・という状況ないですか?ないですね。
SELECT * FROM users ORDER BY (id = 1) DESC, age ASC;
先程の構文が理解できれば説明不要ですね。(id = 1 DESC)
でid
が1のレコードだけ先頭に集まります。
型番の英字部分が特定の値のレコードだけ固定
ECサイトなどで、型番を"A-1"のように「カテゴリー - 連番」で表すことは多いんじゃないかと思います。
「カテゴリーが"XX"の商品はおすすめ品だから、どの基準で並べ替えても先頭に固定したい」という状況ないですか?ないですね。
型番のカテゴリーをmodel_type
、連番をmodel_number
で表している場合(この2つで複合一意制約)を仮定すると、
SELECT * FROM products ORDER BY (model_category = "XX") DESC, model_category ASC, model_number ASC;
これもあらためて説明の必要はないかと思います。
記憶の片隅に残しておくと、いざというときに役に立つかもしれません。
0 件のコメント:
コメントを投稿