【MySQL】日付の降順で並べ替えつつ、NULL(空)の日付は最後に表示する方法
MySQLでNULLの日付を最後に回して並べ替える方法
MySQLで日付カラムを降順にソートするとき、NULL(空)のデータが先頭に来てしまうことがあります。そこで役立つのが、ORDER BY句とIS NULLプロパティを組み合わせたテクニックです。これを使えば、有効な日付で並べ替えを行いながら、NULLのレコードを結果の最後にまとめて配置できます。
基本構文
SELECT * FROM テーブル名 ORDER BY (日付カラム名 IS NULL), 日付カラム名 DESC;
この構文のポイントは、(カラム名 IS NULL)という条件式です。IS NULLは条件が真の場合に 1、偽の場合に 0 を返します。MySQLではデフォルトで昇順(0 → 1)に評価されるため、「NULLではない行(0)」が先に、「NULLの行(1)」が後に並びます。その後ろに日付カラムの降順ソートを指定することで、NULL以外の行だけが新しい日付順に並べ替えられる仕組みです。
動作確認用テーブルの作成
それでは、実際にテーブルを作成して挙動を確認してみましょう。以下のクエリでサンプルテーブルを作成します。
mysql> create table DateColumnWithNullDemo -> ( -> Id int NOT NULL AUTO_INCREMENT, -> LoginDateTime datetime, -> PRIMARY KEY(Id) -> ); Query OK, 0 rows affected (0.84 sec)
テストデータの投入
次に、INSERTコマンドを使ってテストデータを挿入します。意図的にNULLを含むレコードも登録している点に注目してください。
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values(date_add(now(),interval -1 year));
Query OK, 1 row affected (0.15 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values(NULL);
Query OK, 1 row affected (0.17 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values(NULL);
Query OK, 1 row affected (0.12 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values(now());
Query OK, 1 row affected (0.18 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values(curdate());
Query OK, 1 row affected (0.23 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values('2017-08-25 15:30:35');
Query OK, 1 row affected (0.14 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values(NULL);
Query OK, 1 row affected (0.15 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values('2016-12-25 16:55:55');
Query OK, 1 row affected (0.15 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values(NULL);
Query OK, 1 row affected (0.22 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values('2014-11-12 10:20:23');
Query OK, 1 row affected (0.14 sec)
mysql> insert into DateColumnWithNullDemo(LoginDateTime) values('2020-01-01 06:45:23');
Query OK, 1 row affected (0.23 sec)
登録データの確認
SELECT文ですべてのレコードを表示します。
mysql> select *from DateColumnWithNullDemo;
実行結果は以下のとおりです。
+----+---------------------+ | Id | LoginDateTime | +----+---------------------+ | 1 | 2018-01-29 17:07:20 | | 2 | NULL | | 3 | NULL | | 4 | 2019-01-29 17:07:54 | | 5 | 2019-01-29 00:00:00 | | 6 | 2017-08-25 15:30:35 | | 7 | NULL | | 8 | 2016-12-25 16:55:55 | | 9 | NULL | | 10 | 2014-11-12 10:20:23 | | 11 | 2020-01-01 06:45:23 | +----+---------------------+ 11 rows in set (0.00 sec)
このように、NULLを含むレコードが複数混在した状態になっています。
NULLを最後にして日付降順でソートするクエリ
それでは本題のクエリです。「NULL値を最後に配置し、日付は降順で並べ替える」には、次のように記述します。
mysql> select *from DateColumnWithNullDemo -> order by (LoginDateTime IS NULL), LoginDateTime DESC;
実行結果は以下のとおりです。
+----+---------------------+ | Id | LoginDateTime | +----+---------------------+ | 11 | 2020-01-01 06:45:23 | | 4 | 2019-01-29 17:07:54 | | 5 | 2019-01-29 00:00:00 | | 1 | 2018-01-29 17:07:20 | | 6 | 2017-08-25 15:30:35 | | 8 | 2016-12-25 16:55:55 | | 10 | 2014-11-12 10:20:23 | | 2 | NULL | | 3 | NULL | | 7 | NULL | | 9 | NULL | +----+---------------------+ 11 rows in set (0.00 sec)
実行結果のポイント
結果を見ると、日付を持つレコードが新しい順(2020年 → 2014年)に正しく並べ替えられ、その後にNULLのレコードが4件まとめて配置されていることがわかります。
なお、昇順(古い日付順)でソートしたい場合は、2番目の条件をLoginDateTime ASCに変更するだけで対応できます。また、MySQL 8.0以降では ORDER BY LoginDateTime DESC NULLS LAST のような標準SQL構文はサポートされていないため、本記事で紹介した IS NULL を使う方法が最もシンプルかつ確実な手法といえます。
-
MySQLでタイムスタンプを降順に並べ替え、「0000-00-00 00:00:00」だけを先頭に表示する方法
MySQLでORDER BY句を使いタイムスタンプを降順ソートすると、通常は無効な日付である「0000-00-00 00:00:00」は最後尾に配置されます。しかし、ケースによってはこのゼロのタイムスタンプだけを先頭に表示したいこともあるでしょう。本記事では、そのような並べ替えを1つのクエリで実現する方法を解説します。サンプルテーブルの作成まず、以下のコマンドでテーブルを作成します。mysql> create table DemoTable ( `timestamp` timestamp ); Query OK, 0 rows affected (1.12 sec)レコードの挿入
-
MySQLで空の文字列をNULLに更新する方法【LENGTH()関数の使い方】
LENGTH()関数を使って空の文字列をNULLに更新するMySQLで空の文字列()をNULLに置き換えるには、LENGTH()関数を使用します。文字列の長さが0であれば、その文字列が空であると判断できるためです。該当する行を特定したら、UPDATE文のSET句を使ってNULLに設定できます。まずは、動作を確認するためのサンプルテーブルを作成しましょう。mysql> create table DemoTable ( Name varchar(50) ); Query OK, 0 rows affected (0.68 sec)次に、INSE