MySQL中order by 排序遇到NULL值的問題
MySQL數據庫,在order by排序的時候,若是存在NULL值,那麼NULL是最小的,ASC正序排序的話,NULL值是在最前面的。 若是咱們想讓NULL排在後面,讓非NULL的行排在前面該怎麼作呢?mysql
MySQL數據庫在設計的時候,若是字段容許NULL值,那麼對該字段進行排序的時候須要注意那些值爲NULL的行。sql
咱們知道NULL的意思表示什麼都不是,或者理解成「未知」也能夠,它與任何值比較的結果都是false,數據庫
默認狀況下,MySQL會認爲NULL值比其餘類型的數據小,
也就是說,在order by排序的時候,NULL是最小的,ASC正序排序的話,NULL值是在最前面的。
若是咱們想讓NULL排在後面,讓非NULL的行排在前面該怎麼作呢?函數
下面咱們經過一個小例子,來講明這個狀況。測試
首先,建立一個測試數據表 test_user,設計
mysql> create table test_user(
-> id int unsigned not null auto_increment,
-> username varchar(10) not null,
-> age int,
-> primary key (id))
-> engine=myisam
-> default charset=utf8
-> ;
Query OK, 0 rows affected (0.14 sec)排序
填充6條數據,其中3條設置了age值,另外3條age值爲NULLrem
mysql> insert into test_user values(1,'hutuseng1',28),(2,'hutuseng2',30);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0table
mysql> insert into test_user(username) values('hutuseng3'),('hutuseng4'),('hutuseng5');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0test
mysql> insert into test_user values(6,'hutuseng6',23);
Query OK, 1 row affected (0.00 sec)
mysql> select * from test_user;
+----+-----------+------+
| id | username | age |
+----+-----------+------+
| 1 | hutuseng1 | 28 |
| 2 | hutuseng2 | 30 |
| 3 | hutuseng3 | NULL |
| 4 | hutuseng4 | NULL |
| 5 | hutuseng5 | NULL |
| 6 | hutuseng6 | 23 |
+----+-----------+------+
6 rows in set (0.00 sec)
咱們按照age字段從小到大排序,咱們看到NULL值是最小的,排在了最前面
mysql> select * from test_user order by age;
+----+-----------+------+
| id | username | age |
+----+-----------+------+
| 3 | hutuseng3 | NULL |
| 4 | hutuseng4 | NULL |
| 5 | hutuseng5 | NULL |
| 6 | hutuseng6 | 23 |
| 1 | hutuseng1 | 28 |
| 2 | hutuseng2 | 30 |
+----+-----------+------+
6 rows in set (0.00 sec)
按照age字段從大到小排序,咱們看到NULL值確實是最小的,排在了最後面
mysql> select * from test_user order by age desc;
+----+-----------+------+
| id | username | age |
+----+-----------+------+
| 2 | hutuseng2 | 30 |
| 1 | hutuseng1 | 28 |
| 6 | hutuseng6 | 23 |
| 3 | hutuseng3 | NULL |
| 4 | hutuseng4 | NULL |
| 5 | hutuseng5 | NULL |
+----+-----------+------+
6 rows in set (0.00 sec)
這裏有個須要注意的事項,就是NULL值自己是沒法排序的,也就是說一個NULL是沒法和另一個NULL比較的。
你可能已經發現了,那三個NULL值的行,無論正序仍是倒序,順序都是一致的,固然也可能不一致。
那若是在對age進行正序排序的時候,咱們但願NULL值的記錄在最後面顯示,那該如何作呢?
一、從新生成一列,好比agenull,利用is null操做符,把NULL值的行變成1,非NULL值的行變成0,先對該字段排序,再對age排序
mysql> select *,age is null as agenull from test_user order by agenull,age;
+----+-----------+------+---------+
| id | username | age | agenull |
+----+-----------+------+---------+
| 6 | hutuseng6 | 23 | 0 |
| 1 | hutuseng1 | 28 | 0 |
| 2 | hutuseng2 | 30 | 0 |
| 3 | hutuseng3 | NULL | 1 |
| 4 | hutuseng4 | NULL | 1 |
| 5 | hutuseng5 | NULL | 1 |
+----+-----------+------+---------+
6 rows in set (0.01 sec)
二、直接利用isnull函數對age列求值,跟第一種方法的道理是同樣的
mysql> select * from test_user order by isnull(age),age;
+----+-----------+------+
| id | username | age |
+----+-----------+------+
| 6 | hutuseng6 | 23 |
| 1 | hutuseng1 | 28 |
| 2 | hutuseng2 | 30 |
| 3 | hutuseng3 | NULL |
| 4 | hutuseng4 | NULL |
| 5 | hutuseng5 | NULL |
+----+-----------+------+
6 rows in set (0.00 sec)
三、還能夠利用MySQL中的一個小技巧,在字段前面加上一個負號,也就是減號,ASC改爲DESC ,DESC改爲ASC
mysql> select * from test_user order by -age desc;
+----+-----------+------+
| id | username | age |
+----+-----------+------+
| 6 | hutuseng6 | 23 |
| 1 | hutuseng1 | 28 |
| 2 | hutuseng2 | 30 |
| 3 | hutuseng3 | NULL |
| 4 | hutuseng4 | NULL |
| 5 | hutuseng5 | NULL |
+----+-----------+------+
6 rows in set (0.00 sec)
因此,在設計數據庫的時候,若是某個字段要進行排序的話,最好不要爲NULL。