MySQL全面瓦解9:查詢的排序、分頁相關


概述

數據庫中的數據直接呈現出來一般不是我們想要的,所以我們上兩節演示了如何對數據進行過濾的方法。除了對數據進行過濾,

我們可能還需要對數據進行排序,比如想從列表中了解消費最高的項,就可能需要對金額字段做降序排序,想看年齡從小到大的分布情況,就可能需要對user表的age字段進行升序排序。

也可能需要對數據進行限制,比如我們需要對付款的1~10,11~20,21~30 名的用戶分別贈予不同的禮品,這時候對數據的限制就很有用了。

備注:下面腳本中[]包含的表示可選,| 分隔符表示可選其一。

數據排序 order by

語法格式如下:

1、需要排序的字段跟在order by之后;

2、asc 和 desc表示排序的規則,asc:升序,desc:降序,默認為升序 asc;

3、排序可以指定多次字段,多字段排序之間用逗號隔開。

4、多字段排序中,越靠前優先級越高,下面中cname1優先排序,當cname1等值的時候,cname2開始排序,直至所有字段都排序完。

1 select cname from tname order by cname1 [asc|desc],cname2 [asc|desc]...;

 

單個字段排序

舉個例子,在銷售額中通按照交易的訂單進行金額額度降序的方式顯示:

 1 mysql> select * from t_order;
 2 +---------+---------+---------+-------+
 3 | orderid | account | amount  | goods |
 4 +---------+---------+---------+-------+
 5 |       8 | brand   | 52.2    |     2 |
 6 |       9 | hen     | 1752.02 |     7 |
 7 |      10 | helyn   | 88.5    |     4 |
 8 |      11 | sol     | 1007.9  |    11 |
 9 |      12 | diny    | 12      |     1 |
10 |      13 | weng    | 52.2    |     5 |
11 |      14 | sally   | 99.71   |     9 |
12 +---------+---------+---------+-------+
13 7 rows in set
14 
15 mysql> select * from t_order order by amount desc;
16 +---------+---------+---------+-------+
17 | orderid | account | amount  | goods |
18 +---------+---------+---------+-------+
19 |       9 | hen     | 1752.02 |     7 |
20 |      11 | sol     | 1007.9  |    11 |
21 |      14 | sally   | 99.71   |     9 |
22 |      10 | helyn   | 88.5    |     4 |
23 |       8 | brand   | 52.2    |     2 |
24 |      13 | weng    | 52.2    |     5 |
25 |      12 | diny    | 12      |     1 |
26 +---------+---------+---------+-------+
27 7 rows in set

 

多個字段排序

多個字段排序用逗號隔開,優先級從左到右逐次遞減,如下圖,如果金額一致,則按照購買商品數量從多到少排序:

 1 mysql> select * from t_order order by amount desc,goods desc;
 2 +---------+---------+---------+-------+
 3 | orderid | account | amount  | goods |
 4 +---------+---------+---------+-------+
 5 |       9 | hen     | 1752.02 |     7 |
 6 |      11 | sol     | 1007.9  |    11 |
 7 |      14 | sally   | 99.71   |     9 |
 8 |      10 | helyn   | 88.5    |     4 |
 9 |      13 | weng    | 52.2    |     5 |
10 |       8 | brand   | 52.2    |     2 |
11 |      12 | diny    | 12      |     1 |
12 +---------+---------+---------+-------+
13 7 rows in set

按alias排序

按照別名排序或者做條件查詢的目的都是為了簡化代碼,方便使用,別名可以是英文,也可以是中文:

 1 mysql> select account as ac,amount as am,goods as gd from t_order order by am,gd desc;
 2    
 3 +-------+---------+----+
 4 | ac    | am      | gd |
 5 +-------+---------+----+
 6 | diny  | 12      |  1 |
 7 | weng  | 52.2    |  5 |
 8 | brand | 52.2    |  2 |
 9 | helyn | 88.5    |  4 |
10 | sally | 99.71   |  9 |
11 | sol   | 1007.9  | 11 |
12 | hen   | 1752.02 |  7 |
13 +-------+---------+----+
14 7 rows in set

 

字段排序中使用函數

下面使用了abs取絕對值函數,所以在 am字段降序排序中,-99.99 排在 99.71之上。

 1 mysql> select * from t_order;
 2 +---------+---------+---------+-------+
 3 | orderid | account | amount  | goods |
 4 +---------+---------+---------+-------+
 5 |       8 | brand   | 52.2    |     2 |
 6 |       9 | hen     | 1752.02 |     7 |
 7 |      10 | helyn   | 88.5    |     4 |
 8 |      11 | sol     | 1007.9  |    11 |
 9 |      12 | diny    | 12      |     1 |
10 |      13 | weng    | 52.2    |     5 |
11 |      14 | sally   | 99.71   |     9 |
12 |      15 | brand1  | -99.99  |     5 |
13 +---------+---------+---------+-------+
14 8 rows in set
15 
16 mysql> select account as ac,amount as am,goods as gd from t_order order by abs(am) desc;
17    
18 +--------+---------+----+
19 | ac     | am      | gd |
20 +--------+---------+----+
21 | hen    | 1752.02 |  7 |
22 | sol    | 1007.9  | 11 |
23 | brand1 | -99.99  |  5 |
24 | sally  | 99.71   |  9 |
25 | helyn  | 88.5    |  4 |
26 | brand  | 52.2    |  2 |
27 | weng   | 52.2    |  5 |
28 | diny   | 12      |  1 |
29 +--------+---------+----+
30 8 rows in set

與Where條件結合使用

order 在 where 條件之后,根據where已經過濾好的數據再進行排序。下面是過濾出購買金額>80 且 購買數量>5的數據,並且按照價格降序排序。

 1 mysql> select * from t_order;
 2 +---------+---------+---------+-------+
 3 | orderid | account | amount  | goods |
 4 +---------+---------+---------+-------+
 5 |       8 | brand   | 52.2    |     2 |
 6 |       9 | hen     | 1752.02 |     7 |
 7 |      10 | helyn   | 88.5    |     4 |
 8 |      11 | sol     | 1007.9  |    11 |
 9 |      12 | diny    | 12      |     1 |
10 |      13 | weng    | 52.2    |     5 |
11 |      14 | sally   | 99.71   |     9 |
12 |      15 | brand1  | -99.99  |     5 |
13 +---------+---------+---------+-------+
14 8 rows in set
15 
16 mysql> select * from t_order where amount>80 and goods>5 order by amount desc;
17 +---------+---------+---------+-------+
18 | orderid | account | amount  | goods |
19 +---------+---------+---------+-------+
20 |       9 | hen     | 1752.02 |     7 |
21 |      11 | sol     | 1007.9  |    11 |
22 |      14 | sally   | 99.71   |     9 |
23 +---------+---------+---------+-------+

數據limit

很多時候我們過濾出符合要求的數據之后,還需要得到這些數據中的某一個具體區間,比如對付款超過1000的用戶的第1~10,11~20,21~30 名分別贈予不同的禮品,這時候就要使用limit操作了。

limit用來限制select查詢返回的數據,常用於數據排行或者分頁等情況。

語法格式如下:

1 select cname from tname limit [offset,] count;

 

1、offset表示偏移量,就是指跳過的行數,可以省略不寫,默認為0,表示跳過0行,如 limit 8 等同於 limit 0,8。

2、count:跳過偏移量offset之后開始取的數據行數,有count行。

3、limit中offset和count的值不能用表達式。

獲取前n條記錄

如下圖,limit n 和 limit 0,n 是一致的:

 1 mysql> select * from t_order;
 2 +---------+---------+---------+-------+
 3 | orderid | account | amount  | goods |
 4 +---------+---------+---------+-------+
 5 |       8 | brand   | 52.2    |     2 |
 6 |       9 | hen     | 1752.02 |     7 |
 7 |      10 | helyn   | 88.5    |     4 |
 8 |      11 | sol     | 1007.9  |    11 |
 9 |      12 | diny    | 12      |     1 |
10 |      13 | weng    | 52.2    |     5 |
11 |      14 | sally   | 99.71   |     9 |
12 |      15 | brand1  | -99.99  |     5 |
13 +---------+---------+---------+-------+
14 8 rows in set
15 
16 mysql> select * from t_order limit 2
17 ;
18 +---------+---------+---------+-------+
19 | orderid | account | amount  | goods |
20 +---------+---------+---------+-------+
21 |       8 | brand   | 52.2    |     2 |
22 |       9 | hen     | 1752.02 |     7 |
23 +---------+---------+---------+-------+
24 2 rows in set
25 
26 mysql> select * from t_order limit 0,2;
27 +---------+---------+---------+-------+
28 | orderid | account | amount  | goods |
29 +---------+---------+---------+-------+
30 |       8 | brand   | 52.2    |     2 |
31 |       9 | hen     | 1752.02 |     7 |
32 +---------+---------+---------+-------+
33 2 rows in set 

limit限制單條記錄

這邊我們獲取支付金額中最大和最小的的一條記錄。可以先使用 order 條件進行排序,然后limit 第1條記錄即可:

 1  1 mysql> select * from t_order;
 2  2 +---------+---------+---------+-------+
 3  3 | orderid | account | amount  | goods |
 4  4 +---------+---------+---------+-------+
 5  5 |       8 | brand   | 52.2    |     2 |
 6  6 |       9 | hen     | 1752.02 |     7 |
 7  7 |      10 | helyn   | 88.5    |     4 |
 8  8 |      11 | sol     | 1007.9  |    11 |
 9  9 |      12 | diny    | 12      |     1 |
10 10 |      13 | weng    | 52.2    |     5 |
11 11 |      14 | sally   | 99.71   |     9 |
12 12 |      15 | brand1  | -99.99  |     5 |
13 13 +---------+---------+---------+-------+
14 14 8 rows in set
15 15 
16 16 mysql> select * from t_order where amount>0 order by amount desc limit 1;
17 17 +---------+---------+---------+-------+
18 18 | orderid | account | amount  | goods |
19 19 +---------+---------+---------+-------+
20 20 |       9 | hen     | 1752.02 |     7 |
21 21 +---------+---------+---------+-------+
22 22 1 row in set
23 23 
24 24 mysql> select * from t_order where amount>0 order by amount asc limit 1;
25 25 +---------+---------+--------+-------+
26 26 | orderid | account | amount | goods |
27 27 +---------+---------+--------+-------+
28 28 |      12 | diny    | 12     |     1 |
29 29 +---------+---------+--------+-------+
30 30 1 row in set
31  

獲取(m,n)區間記錄

即跳過m條,獲取n條,示例如下,我們跳過兩條,從第三條開始,連取四條的操作:

 1 mysql> select * from t_order order by amount;
 2 +---------+---------+---------+-------+
 3 | orderid | account | amount  | goods |
 4 +---------+---------+---------+-------+
 5 |      15 | brand1  | -99.99  |     5 |
 6 |      12 | diny    | 12      |     1 |
 7 |       8 | brand   | 52.2    |     2 |
 8 |      13 | weng    | 52.2    |     5 |
 9 |      10 | helyn   | 88.5    |     4 |
10 |      14 | sally   | 99.71   |     9 |
11 |      11 | sol     | 1007.9  |    11 |
12 |       9 | hen     | 1752.02 |     7 |
13 +---------+---------+---------+-------+
14 8 rows in set
15 
16 mysql> select * from t_order order by amount limit 2,4;
17 +---------+---------+--------+-------+
18 | orderid | account | amount | goods |
19 +---------+---------+--------+-------+
20 |       8 | brand   | 52.2   |     2 |
21 |      13 | weng    | 52.2   |     5 |
22 |      10 | helyn   | 88.5   |     4 |
23 |      14 | sally   | 99.71  |     9 |
24 +---------+---------+--------+-------+
25 4 rows in set

 

分頁的做法與這個類似,我們程序業務上看到的分頁一般有 pageIndex,pageSize等參數,我們通常的做法是 limit pageIndex*pageSize,pageSize。

這邊假設有31條數據,每頁數量pageSize=10,頁面索引pageIndex默認0,則第一頁就是 limit 0,10,第二頁 limit10,10,第三頁 limit 20,10,第四頁 limit 30,10。

注意點:

1、limit 后面不能使用表達式,只能使用明確的數值,否則會爆出異常,比如 limit 0*10,10,是不對的,這個上面提過了。

2、limit后續的數值只能是正整數和0,也就是說,不能是負數,否則同樣會報錯。

3、排序字段的值相同情況下,排序后分頁會出現混亂重復的情況。

第3點詳細說明下:假如根據age排序,但是有多個age都是20歲的同學,這時候我們3條記錄一頁,就會出現分頁混亂數據重復。因為年齡相同的人有多個,這是幾個人的排序在每次查詢的時候會有不確定性。

舉個例子,下面的分頁,混亂了:

 1 mysql> select * from user3;
 2 +----+------+-------+
 3 | id | age  | name  |
 4 +----+------+-------+
 5 |  1 |   20 | brand |
 6 |  2 |   22 | sol   |
 7 |  3 |   20 | helen |
 8 |  4 | 19.5 | diny  |
 9 |  6 |   19 | a     |
10 |  7 |   20 | b     |
11 |  8 |   20 | c     |
12 |  9 |   20 | d     |
13 | 10 |   20 | e     |
14 | 11 |   23 | f     |
15 +----+------+-------+
16 10 rows in set
17 
18 mysql> select * from user3 order by age limit 0,3; 
19 +----+------+-------+
20 | id | age  | name  |
21 +----+------+-------+
22 |  6 |   19 | a     |
23 |  4 | 19.5 | diny  |
24 |  3 |   20 | helen |
25 +----+------+-------+
26 3 rows in set
27 
28 mysql> select * from user3 order by age limit 3,3;
29  
30 +----+-----+-------+
31 | id | age | name  |
32 +----+-----+-------+
33 |  3 |  20 | helen |
34 |  7 |  20 | b     |
35 |  8 |  20 | c     |
36 +----+-----+-------+
37 3 rows in set
38 
39 mysql> select * from user3 order by age limit 6,3;
40  
41 +----+-----+-------+
42 | id | age | name  |
43 +----+-----+-------+
44 |  7 |  20 | b     |
45 |  3 |  20 | helen |
46 |  2 |  22 | sol   |
47 +----+-----+-------+
48 3 rows in set 

我們的做法是使用重復值字段做排序的時候再加個唯一依據(一般可以設主鍵),就不會混亂了。

如下示例,正常了:

 1 mysql> select * from user3;
 2 +----+------+-------+
 3 | id | age  | name  |
 4 +----+------+-------+
 5 |  1 |   20 | brand |
 6 |  2 |   22 | sol   |
 7 |  3 |   20 | helen |
 8 |  4 | 19.5 | diny  |
 9 |  6 |   19 | a     |
10 |  7 |   20 | b     |
11 |  8 |   20 | c     |
12 |  9 |   20 | d     |
13 | 10 |   20 | e     |
14 | 11 |   23 | f     |
15 +----+------+-------+
16 10 rows in set
17 
18 mysql> select * from user3 order by age,id limit 0,3;
19  
20 +----+------+-------+
21 | id | age  | name  |
22 +----+------+-------+
23 |  6 |   19 | a     |
24 |  4 | 19.5 | diny  |
25 |  1 |   20 | brand |
26 +----+------+-------+
27 3 rows in set
28 
29 mysql> select * from user3 order by age,id limit 3,3;
30  
31 +----+-----+-------+
32 | id | age | name  |
33 +----+-----+-------+
34 |  3 |  20 | helen |
35 |  7 |  20 | b     |
36 |  8 |  20 | c     |
37 +----+-----+-------+
38 3 rows in set
39 
40 mysql> select * from user3 order by age,id limit 6,3;
41  
42 +----+-----+------+
43 | id | age | name |
44 +----+-----+------+
45 |  9 |  20 | d    |
46 | 10 |  20 | e    |
47 |  2 |  22 | sol  |
48 +----+-----+------+
49 3 rows in set

上述總結

1、order by cname [asc|desc] 用於對查詢結果排序,asc為升序,desc為降序,可以省略,省略情況下默認為asc。

2、limit用來限制查詢結果返回的行數,包含2個參數(offset,count),offset:表示跳過多少行,count:表示跳過offset行之后取的行數。limit中offset可以省略,默認值為0;limit中offset 和 count都必須大於等於0;limit中offset和count的值不能用表達式。

3、分頁排序時,排序字段不要有重復值,重復值情況下可能會導致分頁結果混亂,建議在后面加一個主鍵排序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM