MySQL中order by 排序遇到NULL值的問題

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。

相關文章
相關標籤/搜索