MySQLで通常のソートでは0やNULLは先頭に並べられてしまいます。
これを回避して、NULLや0はソートの最後にする方法を紹介します。
LaravelのEloquentでの記載方法も紹介します。
テスト用のテーブルとレコードを作成するSQL
CREATE TABLE tests (`id` INT PRIMARY KEY AUTO_INCREMENT,`rank` INT);
INSERT INTO tests (`rank`) VALUES (NULL),(0),(1),(2),(3);
通常の動作
SELECT * FROM tests
ORDER BY
`rank` ASC;
+----+------+
| id | rank |
+----+------+
| 1 | NULL |
| 2 | 0 |
| 3 | 1 |
| 4 | 2 |
| 5 | 3 |
+----+------+
NULLを最後に並べたい場合
SELECT * FROM tests
ORDER BY
`rank` IS NULL ASC, -- 追加
`rank` ASC;
+----+------+
| id | rank |
+----+------+
| 2 | 0 |
| 3 | 1 |
| 4 | 2 |
| 5 | 3 |
| 1 | NULL |
+----+------+
LaravelのEloquentでのコードはこのようになります。
Tests::orderByRaw('rank IS NULL ASC')
->orderBy('rank', 'ASC')
->get();
NULLと0を最後に並べたい場合
SELECT * FROM tests
ORDER BY
`rank` IS NULL ASC, -- 追加
`rank` = 0 ASC, -- 追加
`rank` ASC;
+----+------+
| id | rank |
+----+------+
| 3 | 1 |
| 4 | 2 |
| 5 | 3 |
| 2 | 0 |
| 1 | NULL |
+----+------+
NULLは最後にして降順に並べたい場合
SELECT * FROM tests
ORDER BY
`rank` IS NULL ASC,
`rank` DESC; -- DESCにする
+----+------+
| id | rank |
+----+------+
| 5 | 3 |
| 4 | 2 |
| 3 | 1 |
| 2 | 0 |
| 1 | NULL |
+----+------+
おまけ:うまくいかない場合
ORDER BYの順序が異なるとうまくいかないです。
SELECT * FROM tests
ORDER BY
`rank` = 0 ASC,
`rank` IS NULL ASC, -- 0とNULLの順番を逆にした
`rank` ASC;
+----+------+
| id | rank |
+----+------+
| 1 | NULL |
| 3 | 1 |
| 4 | 2 |
| 5 | 3 |
| 2 | 0 |
+----+------+
コメント