目錄
注:有關MySql數據庫的其他操作請參見MySql目錄進行查找。
一、本篇作爲例子的三個表
學號(Sno) |
姓名(Sname) | 性別(Ssex) | 年齡(Sage) | 所在系(Sdept) |
201215121 | 李勇 | 男 | 20 | CS |
201215122 | 劉晨 | 女 | 19 |
CS |
201215123 | 王敏 | 女 | 18 | MA |
201215125 | 張立 | 男 | 19 | IS |
Course
課程號(Cno) | 課程名(Cname) | 先行課(Cpno) | 學分(Ccredit) |
1 | 數據庫 | 5 | 4 |
2 | 數學 | 2 | |
3 | 信息系統 | 1 | 4 |
4 | 操作系統 | 6 | 3 |
5 | 數據結構 | 7 | 4 |
6 | 數據處理 | 2 | |
7 | PASCAL語言 | 6 | 4 |
SC
學號(Sno) | 課程號(Cno) | 成績(Grade) |
201215121 | 1 | 92 |
201215121 | 2 | 85 |
201215121 | 3 | 88 |
201215122 | 2 | 90 |
201215122 | 3 | 80 |
二、單表查詢
1、選擇表中的的若干列
(1) 查詢指定列
格式:select 屬性名,屬性名,... from 表名;
例子:select Sno, Sname from Student;
(2)查詢全部列
select * from Student;
(3)查詢經過計算的值
屬性名可以替換爲算術表達式、字符串常量、函數等。
例1:select Sname, 2019-Sage from Student;(算術表達式)
例2:select Sname, 'Year of Birth: ', 2019-Sage, lower(Sdept) from Student;
用戶還可以通過指定別名來改變查詢結果的列標題。
2、選擇表中的若干元組
(1)消除取值重複的行
因爲查詢某些列後可能會有元組擁有相同的取值,因此可以通過增加單詞distinct來消除重複的行。
例:select distinct Sno from SC;
(2)查詢滿足條件的元組
1) 比較大小(=,>,<,>=,<=,!=,!>,!<)
例:select Sname, Sage from Student where Sage<20;
2) 確定範圍
例:select Sname, Sdept, Sage from Student where Sage [not] between 20 and 23;
3) 確定集合
例:select Sname, Ssex from Student where Sdept [not] in ('CS', 'MA', 'IS');
4) 字符匹配
可以使用like來進行字符串的匹配。其中有兩種通配符:%和_。另外若在通配符前加上\則不再具有通配符的含義。
%:表示任意長度的字符串。
_:表示任意單個字符。
例1:select * from Student where Sno like '201215121';
例2:select Sname, Sno, Ssex from Student where Sname like 'liu%';
例3:select Sname from Student where Sname like '_iuchen';
5) 涉及空值的查詢
例:select Sno, Cno from SC where Grade is NULL;
6) 多重條件查詢
例:select Sname from Student where Sdept='CS' and Sage<20;
(3)ORDER BY 子句
用戶可以用order by子句對查詢結果按照一個或多個屬性列的升序(ASC)或者降序(DESC)排列,默認值爲升序。
例1:SELECT Sno, Grade FROM SC WHERE Cno='3' ORDER BY Grade DESC;
解釋:查詢結果按分數降序排序。
例2:SELECT * FROM Student ORDER BY Sdept, Sage DESC;
解釋:查詢結果按所在系升序排序,同一系中的學生按年齡降序排列。
(4)聚集函數(自帶函數)
聚集函數主要又下列幾種:
-
COUNT(*):統計元組個數
例:SELECT COUNT(*) FROM Student;
-
COUNT(列名):統計某列中元組的個數
例:SELECT COUNT(DISTINCT Sno) FROM SC;
-
SUM(列名):計算一列值的總和
例:SELECT AVG(Grade) FROM SC WHERE Cno='1';
-
AVG(列名):計算一列值的平均值
例:SELECT AVG(Grade) FROM SC WHERE Cno='1';
-
MAX(列名):一列值中的最大值
例:SELECT MAX(Grade) FROM SC WHERE Cno='1';
-
MIN(列名):一列值中的最小值
例:SELECT MIN(Grade) FROM SC WHERE Cno='1';
注:聚集函數不能作爲條件表達式,只能用於SELECT子句和GROUP BY中的HAVING子句。
(5)GROUP BY 子句
GROUP BY子句將查詢結果按某一列或多列的值分組,值相等的爲一組。
對查詢結果分組的目的是爲了細化聚集函數的作用對象。分組後聚集函數將作用於每組。
例1:SELECT Cno, COUNT(Sno) FROM SC GROUP BY Cno;
解釋:語句對查詢結果按Cno的值分組,所有具有相同Cno的值的元組爲一組,然後對每一組作用聚集函數COUNT進行計算,求得該組學生人數。
GROUPBY 還可以使用HAVING短語按一定條件對這些組進行篩選最終輸出滿足指定條件的組。
例2:SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*) > 3;
例3:SELECT Sno, AVG(Grade) FROM SC GROUP BY Sno HAVING AVG(Grade) >= 90;
注意:這裏的聚集函數使用在HAVING 短語中而非用在WHERE的條件表達式中。
三、連接查詢
1、等值與非等值連接查詢
當連接運算符爲=時,稱爲等值連接。使用其他運算符稱爲非等值連接。
等值連接例1:SELECT Student.*, SC.* FROM Student, SC WHERE Student.Sno=SC.Sno;
非等值連接例2:SELECT Student.Sno, Sname FROM Student, SC WHERE Student.Sno=SC.Sno AND SC.Cno='2' AND SC.Grade>90;
注意:若選擇的屬性列在兩個表中是唯一的,則可以省去表名前綴;若不唯一,則引用時必須加上表名前綴。
2、自身連接
連接操作不僅可以在兩個表之間進行,也可以是一個表與其自身進行連接,稱爲表的自身連接。
例:查詢一門課的間接先修課。
SELECT FIRST.Cno, SECOND.Cpno FROM Course FIRST, Course SECOND WHERE FIRST.Cpno=SECOND.Cno;
注意:爲了區分自身的兩個表而給這兩個表分別取了別名FIRST和SECOND。
3、外連接
兩個表進行連接時,若其中一個表沒有相關的元組信息,則按普通的兩表連接則會省去某些元組,若想保留則可以使用外連接。
例:SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade FROM Student LEFT OUTER JOIN SC ON (Student.Sno=SC.Sno);
4、多表連接
還可以進行兩個表以上的連接,稱爲多表連接。
例:SELECT Student.Sno, Sname, Cname, Grade FROM Student, SC, Course WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
四、嵌套查詢
概念:一個SELECT-FROM-WHERE語句稱爲一個查詢塊。將一個查詢塊嵌套在另一個查詢塊的WHERE子句或HAVING短語的條件中的查詢稱爲嵌套查詢。
1、帶有IN謂詞的子查詢
例:SELECT Sno, Sname, Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname='liuchen');
解釋:查詢與“liuchen”在同一個系的學生。
注意:有些查詢可以用連接查詢替代,有些是不能替代的。
2、帶有比較運算符的子查詢
例:SELECT Sno, Cno FROM SC x WHERE Grade >= (SELECT AVG(Grade) FROM SC y WHERE y.Sno=x.Sno);
解釋:查詢每個學生超過他自己選修課程平均成績的課程號。
注意:這個子查詢與父查詢相關,因此這類查詢稱爲相關子查詢。
3、帶有ANY(SOME) 或ALL謂詞的子查詢
子查詢返回多值時需要使用ANY和ALL謂詞修飾。其中:
ANY:表示某個 ALL:表示所有
例1:SELECT Sname, Sage FROM Student WHERE Sage<ANY(SELECT Sage FROM Student WHERE Sdept='CS') AND Sdept<>'CS';
解釋:查詢非計算機系中比計算機科學系某個學生年齡小的學生姓名和年齡。
例2:SELECT Sname, Sage FROM Student WHERE Sage<ALL(SELECT Sage FROM Student WHERE Sdept='CS') AND Sdept<>'CS';
解釋:查詢非計算機系中比計算機科學系所有學生年齡小的學生姓名和年齡。
4、帶有EXISTS謂詞的子查詢
帶有EXISTS謂詞的子查詢不返回任何數據,只產生邏輯結果真值“true”或邏輯假值“false”。
例1:SELECT Sname FROM Student WHERE EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno='1');
解釋:查詢所有選修了1號課程的學生姓名。
例2:SELECT Sname FROM Student WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno='1');
解釋:查詢沒有選修了1號課程的學生姓名。
注:EXISTS還可以用來進行量詞轉化後進行查詢。
五、集合查詢
集合操作包括:並操作(UNION)、交操作(INTERSECT)、差操作(EXCEPT)
例1:SELECT * FROM Student WHERE Sdept='CS' UNION SELECT * FROM Student WHERE Sage<=19;
解釋:查詢計算機科學系的學生及年齡不大於19歲的學生。
另外MySql並沒有提供對交和差操作的支持,這裏就不再舉例。
六、基於派生表的查詢
子查詢不僅可以出現在WHERE子句中,也可以出現在FROM子句中,這時子查詢生成的臨時派生表成爲主查詢的查詢對象。
例:SELECT Sname FROM Student, (SELECT Sno FROM SC WHERE Cno='1') AS SC1 WHERE Student.Sno=SC1.Sno;