上集中咱們嘮叨了數據庫的建立、選擇和刪除,表的建立、修改和刪除以及簡單的查詢和插入命令。可是這只是搭建了一個空架子,其實對於MySQL
來講,咱們平時使用頻率最高的仍是查詢功能,本集將詳細聚焦各類讓人眼花繚亂的查詢方式,認真看,仔細看,滴點兒莎普愛思拿抹布擦擦眼繼續看!本集的東西真的很是重要!mysql
話說本集的主題是查詢數據,因此先得肯定一下查哪一個表吧,肯定了表以後表裏頭先得有數據吧,要不查個屁呀~ 因此咱們先搞定用什麼表和爲表中填入數據的工做。程序員
爲簡單起見,咱們就複用以前在數據庫xiaohaizi
下邊建立的學生信息表student_info
和學生成績表student_score
,你可能有點忘了這兩個表長啥樣了,咱們先把兩個表的結構回顧一下:sql
CREATE TABLE student_info (
number INT PRIMARY KEY,
name VARCHAR(5),
sex ENUM('男', '女'),
id_number CHAR(18),
department VARCHAR(30),
major VARCHAR(30),
enrollment_time DATE,
UNIQUE KEY (id_number)
);
複製代碼
CREATE TABLE student_score (
number INT,
subject VARCHAR(30),
score TINYINT,
PRIMARY KEY (number, subject),
CONSTRAINT FOREIGN KEY(number) REFERENCES student_info(number)
);
複製代碼
咱們給這兩個表插入一些數據:數據庫
mysql> INSERT INTO student_info(number, name, sex, id_number, department, major, enrollment_time) VALUES
-> (20180101, '杜子騰', '男', '158177199901044792', '計算機學院', '計算機科學與工程', '2018-09-01'),
-> (20180102, '杜琦燕', '女', '151008199801178529', '計算機學院', '計算機科學與工程', '2018-09-01'),
-> (20180103, '範統', '男', '17156319980116959X', '計算機學院', '軟件工程', '2018-09-01'),
-> (20180104, '史珍香', '女', '141992199701078600', '計算機學院', '軟件工程', '2018-09-01'),
-> (20180105, '範劍', '男', '181048199308156368', '航天學院', '飛行器設計', '2018-09-01'),
-> (20180106, '朱逸羣', '男', '197995199501078445', '航天學院', '電子信息', '2018-09-01');
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> INSERT INTO student_score (number, subject, score) VALUES
-> (20180101, '母豬的產後護理', 78),
-> (20180101, '論薩達姆的戰爭準備', 88),
-> (20180102, '母豬的產後護理', 100),
-> (20180102, '論薩達姆的戰爭準備', 98),
-> (20180103, '母豬的產後護理', 59),
-> (20180103, '論薩達姆的戰爭準備', 61),
-> (20180104, '母豬的產後護理', 55),
-> (20180104, '論薩達姆的戰爭準備', 46);
Query OK, 8 rows affected (0.00 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql>
複製代碼
如今這兩個表中的數據就以下所示了:bash
number | name | sex | id_number | department | major | enrollment_time |
---|---|---|---|---|---|---|
20180101 | 杜子騰 | 男 | 158177199901044792 | 計算機學院 | 計算機科學與工程 | 2018-09-01 |
20180102 | 杜琦燕 | 女 | 151008199801178529 | 計算機學院 | 計算機科學與工程 | 2018-09-01 |
20180103 | 範統 | 男 | 17156319980116959X | 計算機學院 | 軟件工程 | 2018-09-01 |
20180104 | 史珍香 | 女 | 141992199701078600 | 計算機學院 | 軟件工程 | 2018-09-01 |
20180105 | 範劍 | 男 | 181048200008156368 | 航天學院 | 飛行器設計 | 2018-09-01 |
20180106 | 朱逸羣 | 男 | 197995199801078445 | 航天學院 | 電子信息 | 2018-09-01 |
number | subject | score |
---|---|---|
20180101 | 母豬的產後護理 | 78 |
20180101 | 論薩達姆的戰爭準備 | 88 |
20180102 | 母豬的產後護理 | 100 |
20180102 | 論薩達姆的戰爭準備 | 98 |
20180103 | 母豬的產後護理 | 59 |
20180103 | 論薩達姆的戰爭準備 | 61 |
20180104 | 母豬的產後護理 | 55 |
20180104 | 論薩達姆的戰爭準備 | 46 |
好了,表的填充工做也已經作完了~ 終於能夠開始查詢數據了!性能
查看某個表中的某一列的數據的通用格式是這樣:學習
SELECT 列名 FROM 表名;
複製代碼
好比查看student_info
表中的number
列的數據能夠這麼寫:測試
mysql> SELECT number FROM student_info;
+----------+
| number |
+----------+
| 20180104 |
| 20180102 |
| 20180101 |
| 20180103 |
| 20180105 |
| 20180106 |
+----------+
6 rows in set (0.00 sec)
mysql>
複製代碼
咱們把要查詢的東西稱爲查詢對象
,本例中的查詢對象就是number
列,由於查詢的結果也是由一條一條記錄組成的,像記錄的集合同樣,因此有時候咱們會吧獲得的查詢結果稱爲結果集
。優化
小貼士: 你可能發現查詢出的數據並非有序的,這個咱們稍後就會說到,稍安勿躁 ui
咱們也能夠爲結果集中的列從新定義一個別名
,命令格式以下:
SELECT 列名 [AS] 列的別名 FROM 表名;
複製代碼
咱們看到AS
被加了箇中括號,意味着無關緊要,沒有AS
的話,列名和列的別名用空白字符隔開就行了。好比咱們想給number
列起個別名,下邊這兩種方式均可以使用:
方式一
SELECT number AS 學號 FROM student_info;
複製代碼
方式二:
SELECT number 學號 FROM student_info;
複製代碼
咱們執行一下:
mysql> SELECT number AS 學號 FROM student_info;
+----------+
| 學號 |
+----------+
| 20180104 |
| 20180102 |
| 20180101 |
| 20180103 |
| 20180105 |
| 20180106 |
+----------+
6 rows in set (0.00 sec)
mysql>
複製代碼
看到黑框框裏顯示的列名就再也不是number
,而是咱們剛剛定義的別名學號
了。不過須要注意的是:列名只是做用在本次查詢的顯示結果中,而不會改變真實表中的列名,也就是說下一次查詢中你對number
列取別的列名也能夠,好比這樣:
mysql> SELECT number xuehao FROM student_info;
+----------+
| xuehao |
+----------+
| 20180104 |
| 20180102 |
| 20180101 |
| 20180103 |
| 20180105 |
| 20180106 |
+----------+
6 rows in set (0.00 sec)
mysql>
複製代碼
此次輸出的列名就是另外一個別名xuehao
了。
若是想查詢多個列的數據,能夠在SELECT
後邊寫多個列名,用逗號,
分隔開就好:
SELECT 列名1, 列名2, ... 列名n FROM 表名;
複製代碼
咱們把多個查詢對象
組成的列表稱爲查詢列表
,須要注意的是,查詢列表中的列名能夠按任意順序擺放,結果集將按照咱們給出的列名順序顯示。好比咱們查詢student_info
中的多個列:
mysql> SELECT number, name, id_number, major FROM student_info;
+----------+-----------+--------------------+--------------------------+
| number | name | id_number | major |
+----------+-----------+--------------------+--------------------------+
| 20180101 | 杜子騰 | 158177199901044792 | 計算機科學與工程 |
| 20180102 | 杜琦燕 | 151008199801178529 | 計算機科學與工程 |
| 20180103 | 範統 | 17156319980116959X | 軟件工程 |
| 20180104 | 史珍香 | 141992199701078600 | 軟件工程 |
| 20180105 | 範劍 | 181048199308156368 | 飛行器設計 |
| 20180106 | 朱逸羣 | 197995199501078445 | 電子信息 |
+----------+-----------+--------------------+--------------------------+
6 rows in set (0.00 sec)
mysql>
複製代碼
本例中的查詢列表就是number,name,id_number,major
,因此結果集中列的順序就按找這個順序來顯示。固然,咱們也能夠用別名來輸出這些數據:
mysql> SELECT number AS 學號, name AS 姓名, id_number AS 身份證號, major AS 專業 FROM student_info;
+----------+-----------+--------------------+--------------------------+
| 學號 | 姓名 | 身份證號 | 專業 |
+----------+-----------+--------------------+--------------------------+
| 20180101 | 杜子騰 | 158177199901044792 | 計算機科學與工程 |
| 20180102 | 杜琦燕 | 151008199801178529 | 計算機科學與工程 |
| 20180103 | 範統 | 17156319980116959X | 軟件工程 |
| 20180104 | 史珍香 | 141992199701078600 | 軟件工程 |
| 20180105 | 範劍 | 181048199308156368 | 飛行器設計 |
| 20180106 | 朱逸羣 | 197995199501078445 | 電子信息 |
+----------+-----------+--------------------+--------------------------+
6 rows in set (0.00 sec)
mysql>
複製代碼
若是你樂意,同一個查詢對象能夠在查詢列表處重複出現(雖然這一般沒什麼卵用),好比這樣:
mysql> SELECT number, number, number FROM student_info;
+----------+----------+----------+
| number | number | number |
+----------+----------+----------+
| 20180104 | 20180104 | 20180104 |
| 20180102 | 20180102 | 20180102 |
| 20180101 | 20180101 | 20180101 |
| 20180103 | 20180103 | 20180103 |
| 20180105 | 20180105 | 20180105 |
| 20180106 | 20180106 | 20180106 |
+----------+----------+----------+
6 rows in set (0.00 sec)
mysql>
複製代碼
若是須要把記錄中的全部列都查出來,MySQL
也提供一個省事兒的辦法,咱們以前也介紹過,就是直接用星號*
來表示要查詢的東西,就像這樣:
SELECT * FROM 表名;
複製代碼
這個命令咱們以前看過了,就很少嘮叨了。不過須要注意的是,除非你確實須要表中的每一個列,不然通常最好別使用星號*
來查詢全部列,雖然星號*
看起來很方便,不用明確列出所需的列,可是查詢不須要的列一般會下降性能。
有的時候咱們查詢某個列的數據時會有一些重複的結果,好比咱們查詢一下student_info
表的學院信息:
mysql> SELECT department FROM student_info;
+-----------------+
| department |
+-----------------+
| 計算機學院 |
| 計算機學院 |
| 計算機學院 |
| 計算機學院 |
| 航天學院 |
| 航天學院 |
+-----------------+
6 rows in set (0.00 sec)
複製代碼
由於表裏有6條記錄,因此給咱們返回了6條結果。可是其實好多都是重複的結果,若是咱們想去除重複結果的話,可使用DISTINCT
放在被查詢的列前邊,就是這樣:
SELECT DISTINCT 列名 FROM 表名;
複製代碼
咱們對學院信息作一下去重處理:
mysql> SELECT DISTINCT department FROM student_info;
+-----------------+
| department |
+-----------------+
| 計算機學院 |
| 航天學院 |
+-----------------+
2 rows in set (0.00 sec)
複製代碼
看到結果只剩下不重複的信息了。
對於查詢多列的狀況,兩條記錄重複的意思是:兩條記錄的每個列中的值都相同。好比查詢學院和專業信息:
mysql> SELECT department, major FROM student_info;
+-----------------+--------------------------+
| department | major |
+-----------------+--------------------------+
| 計算機學院 | 計算機科學與工程 |
| 計算機學院 | 計算機科學與工程 |
| 計算機學院 | 軟件工程 |
| 計算機學院 | 軟件工程 |
| 航天學院 | 飛行器設計 |
| 航天學院 | 電子信息 |
+-----------------+--------------------------+
6 rows in set (0.00 sec)
複製代碼
查詢結果中第一、2行記錄中的department
和major
列都相同,因此這兩行記錄就是重複的,同理,第三、4行也是重複的。若是咱們想對多列查詢的結果去重的話,能夠直接把DISTINCT
放在被查詢的列的最前邊:
SELECT DISTINCT 列名1, 列名2, ... 列名n FROM 表名;
複製代碼
好比這樣:
mysql> SELECT DISTINCT department, major FROM student_info;
+-----------------+--------------------------+
| department | major |
+-----------------+--------------------------+
| 計算機學院 | 計算機科學與工程 |
| 計算機學院 | 軟件工程 |
| 航天學院 | 飛行器設計 |
| 航天學院 | 電子信息 |
+-----------------+--------------------------+
4 rows in set (0.00 sec)
mysql>
複製代碼
DISTINCT
不能作到一部分查詢列去重,另外一部分不去重。由於查詢結果是以行爲單位展現的,若是你只對department
去重,那department
那一列只剩下4行數據,對major
列不去重,那major
列剩下了8行數據,那結果應該怎麼展現呢?因此咱們規定DISTINCT
只能用來對所有列的值都相同的記錄來進行去重。
有時候查詢結果的條數會不少,都顯示出來可能會撐爆屏幕~ 因此MySQL
給咱們提供了一種限制結果條數的方式,就是在查詢語句的末尾使用這樣的語法:
LIMIT 開始行, 限制條數;
複製代碼
開始行
指的是咱們想從第幾行數據開始查詢,限制條數
是查詢結果最多返回的記錄條數。
小貼士 在生活中一般都是從1開始計數的,而在計算機中都是從0開始計數的,因此咱們平時所說的第1條記錄在計算機中算是第0條。好比`student_info`表裏的6條記錄在計算機中依次表示爲:第0條、第1條、第2條、第3條、第4條、第5條。
好比咱們查詢一下student_info
表,從第0條記錄開始,最多查詢2條記錄能夠這麼寫:
mysql> SELECT number, name, id_number, major FROM student_info LIMIT 0, 2;
+----------+-----------+--------------------+--------------------------+
| number | name | id_number | major |
+----------+-----------+--------------------+--------------------------+
| 20180101 | 杜子騰 | 158177199901044792 | 計算機科學與工程 |
| 20180102 | 杜琦燕 | 151008199801178529 | 計算機科學與工程 |
+----------+-----------+--------------------+--------------------------+
2 rows in set (0.00 sec)
mysql>
複製代碼
若是指定的開始行
大於結果中的行數,那查詢結果就是什麼都沒有:
mysql> SELECT number, name, id_number, major FROM student_info LIMIT 6, 2;
Empty set (0.00 sec)
mysql>
複製代碼
若是查詢的結果條數小於限制條數
,那就能夠所有顯式出來:
mysql> SELECT number, name, id_number, major FROM student_info LIMIT 4, 3;
+----------+-----------+--------------------+-----------------+
| number | name | id_number | major |
+----------+-----------+--------------------+-----------------+
| 20180105 | 範劍 | 181048199308156368 | 飛行器設計 |
| 20180106 | 朱逸羣 | 197995199501078445 | 電子信息 |
+----------+-----------+--------------------+-----------------+
2 rows in set (0.00 sec)
mysql>
複製代碼
從第4條開始的記錄有兩條,限制條數
爲3,因此結果均可以顯示出來。
LIMIT
後邊也能夠只有一個參數,那這個參數就表明着限制行數
。也就是說咱們能夠不指定開始行
,默認的開始行就是第0行,好比咱們能夠這麼寫:
mysql> SELECT number, name, id_number, major FROM student_info LIMIT 3;
+----------+-----------+--------------------+--------------------------+
| number | name | id_number | major |
+----------+-----------+--------------------+--------------------------+
| 20180101 | 杜子騰 | 158177199901044792 | 計算機科學與工程 |
| 20180102 | 杜琦燕 | 151008199801178529 | 計算機科學與工程 |
| 20180103 | 範統 | 17156319980116959X | 軟件工程 |
+----------+-----------+--------------------+--------------------------+
3 rows in set (0.00 sec)
mysql>
複製代碼
查詢結果就展現了從第0條開始的3條記錄。
咱們以前查詢number
列的時候獲得的記錄並非有序的,這是爲何呢?MySQL
其實默認會按照這些數據底層存儲的順序來給咱們返回數據,可是這些數據可能會通過更新或者刪除,若是咱們不明確指定按照什麼順序來排序返回結果的話,那咱們能夠認爲該結果中記錄的順序是不肯定的。換句話說若是咱們想讓返回結果中的記錄按照某種特定的規則排序,那咱們必須顯式的指定排序規則。
咱們能夠用下邊的語法來指定返回結果的記錄按照某一列的值進行排序:
ORDER BY 列名 ASC|DESC
複製代碼
ASC
和DESC
指的是排序方向。ASC
是指按照指定列的值進行由小到大進行排序,也叫作升序
,DESC
是指按照指定列的值進行由大到小進行排序,也叫作降序
,中間的|
表示這兩種方式只能選一個。這回咱們用student_score
表測試一下:
mysql> SELECT * FROM student_score ORDER BY score ASC;
+----------+-----------------------------+-------+
| number | subject | score |
+----------+-----------------------------+-------+
| 20180104 | 論薩達姆的戰爭準備 | 46 |
| 20180104 | 母豬的產後護理 | 55 |
| 20180103 | 母豬的產後護理 | 59 |
| 20180103 | 論薩達姆的戰爭準備 | 61 |
| 20180101 | 母豬的產後護理 | 78 |
| 20180101 | 論薩達姆的戰爭準備 | 88 |
| 20180102 | 論薩達姆的戰爭準備 | 98 |
| 20180102 | 母豬的產後護理 | 100 |
+----------+-----------------------------+-------+
8 rows in set (0.01 sec)
mysql>
複製代碼
能夠看到輸出的記錄就是按照成績由小到大進行排序的。若是省略了 ORDER BY 語句中的排序方向,則默認按照從小到大的順序進行排序,也就是說ORDER BY 列名
和ORDER BY 列名 ASC
的語義是同樣的,咱們試一下:
mysql> SELECT * FROM student_score ORDER BY score;
+----------+-----------------------------+-------+
| number | subject | score |
+----------+-----------------------------+-------+
| 20180104 | 論薩達姆的戰爭準備 | 46 |
| 20180104 | 母豬的產後護理 | 55 |
| 20180103 | 母豬的產後護理 | 59 |
| 20180103 | 論薩達姆的戰爭準備 | 61 |
| 20180101 | 母豬的產後護理 | 78 |
| 20180101 | 論薩達姆的戰爭準備 | 88 |
| 20180102 | 論薩達姆的戰爭準備 | 98 |
| 20180102 | 母豬的產後護理 | 100 |
+----------+-----------------------------+-------+
8 rows in set (0.01 sec)
複製代碼
再看一下從大到小排序的樣子:
mysql> SELECT * FROM student_score ORDER BY score DESC;
+----------+-----------------------------+-------+
| number | subject | score |
+----------+-----------------------------+-------+
| 20180102 | 母豬的產後護理 | 100 |
| 20180102 | 論薩達姆的戰爭準備 | 98 |
| 20180101 | 論薩達姆的戰爭準備 | 88 |
| 20180101 | 母豬的產後護理 | 78 |
| 20180103 | 論薩達姆的戰爭準備 | 61 |
| 20180103 | 母豬的產後護理 | 59 |
| 20180104 | 母豬的產後護理 | 55 |
| 20180104 | 論薩達姆的戰爭準備 | 46 |
+----------+-----------------------------+-------+
8 rows in set (0.00 sec)
mysql>
複製代碼
咱們也能夠同時指定多個排序的列,多個排序列之間用逗號,
隔開就行了,就是這樣:
ORDER BY 列1 ASC|DESC, 列2 ASC|DESC ...
複製代碼
好比咱們想讓對student_score
的查詢結果先按照subjuect
排序,再按照score
值從大到小的順序進行排列,能夠這麼寫:
mysql> SELECT * FROM student_score ORDER BY subject, score DESC;
+----------+-----------------------------+-------+
| number | subject | score |
+----------+-----------------------------+-------+
| 20180102 | 母豬的產後護理 | 100 |
| 20180101 | 母豬的產後護理 | 78 |
| 20180103 | 母豬的產後護理 | 59 |
| 20180104 | 母豬的產後護理 | 55 |
| 20180102 | 論薩達姆的戰爭準備 | 98 |
| 20180101 | 論薩達姆的戰爭準備 | 88 |
| 20180103 | 論薩達姆的戰爭準備 | 61 |
| 20180104 | 論薩達姆的戰爭準備 | 46 |
+----------+-----------------------------+-------+
8 rows in set (0.00 sec)
mysql>
複製代碼
再提醒一遍,若是不指定排序方向,則默認使用的是ASC
,也就是從小到大的升序規則。
小貼士: 對於數字的排序仍是很好理解的,可是字符串怎麼排序呢?大寫的A和小寫的a哪一個大哪一個小?這個問題涉及到字符串使用的編碼方式以及字符串排序規則,咱們以後會詳細的介紹它們,如今你只須要知道排序的語法就行了。
咱們還可讓ORDER BY
語句和LIMIT
語句結合使用,不過 ORDER BY 語句必須放在 LIMIT 語句前邊,好比這樣:
mysql> SELECT * FROM student_score ORDER BY score LIMIT 1;
+----------+-----------------------------+-------+
| number | subject | score |
+----------+-----------------------------+-------+
| 20180104 | 論薩達姆的戰爭準備 | 46 |
+----------+-----------------------------+-------+
1 row in set (0.00 sec)
mysql>
複製代碼
這樣就能找出成績最低的那條記錄了。
咱們能夠在SELECT後邊指定要查詢的列的列表,而後在FROM後邊指定要查詢的表,能夠只查詢單個列的值,也能夠查詢多個列的值,也可使用*簡單的表明查詢全部列的值。
若是咱們想去除重複結果的話,可使用DISTINCT放在被查詢的列前邊。須要注意的是,兩條記錄重複的意思是,因此使用DISTINCT在多個列上會把兩條記錄的每個列中的值都相同的重複行去掉,而不能作到不能作到一部分列去重,另外一部分不去重。
使用LIMIT語句限制查詢結果的行數,LIMIT子句能夠攜帶兩個參數,其中開始行指的是咱們想從第幾行數據開始查詢,限制條數是查詢結果最多返回的記錄條數。參數開始行能夠被省略,默認從第0行開始。
若是咱們想讓返回結果中的記錄按照某種特定的規則排序,那咱們必須顯式的使用ORDER BY指定排序規則。其中,ASC指按照指定列的值的升序排序,DESC指按照指定列的值的降序排序。若是ORDER BY子句後有多個列的話,會先按照前邊的列進行排序,若是前邊的列的值相同,在相同的這些行中再按照後邊的列進行排序。
本系列專欄都是MySQL入門知識,想看進階知識能夠到小冊中查看:《MySQL是怎樣運行的:從根兒上理解MySQL》的連接 。小冊的內容主要是從小白的角度出發,用比較通俗的語言講解關於MySQL進階的一些核心概念,好比記錄、索引、頁面、表空間、查詢優化、事務和鎖等,總共的字數大約是三四十萬字,配有上百幅原創插圖。主要是想下降普通程序員學習MySQL進階的難度,讓學習曲線更平滑一點~