簡單查詢
(3)查詢經過計算的值
SELECT子句的<目標列表達式>不僅可以是表中的屬性列,也可以是有關表達式,即可以將查詢出來的屬性列經過一定的計算後列出結果。
例8 查詢全體學生的姓名及其出生年份
SELECT Sname, 2004-Sage FROM Student;
本例中,<目標列表達式>中第二項不是通常的列名,而是一個計算表達式,是用當前的年份(假設為2004年)減去學生的年齡,這樣,所得的即是學生的出身年份。輸出的結果為:
Sname
------ ----------
李勇 1976
劉晨 1977
王名 1978
張立 1978
不僅可以是算術表達式,還可以是字符串常量、函數等。
例9 查詢全體學生的姓名、出生年份和所有系
SELECT Sname, 'Year of Birth:', 2004-Sage 出生年份 FROM Student;
結果為:
Sname 出生年份
------ -------------------------
李勇 Year of Birth: 1976
劉晨 Year of Birth: 1977
王名 Year of Birth: 1978
張立 Year of Birth: 1978
用戶可以通過指定別名來改變查詢結果的列標題,這對於含算術表達式、常量、函數名的目標列表達式尤為有用。
2.選擇表中的若干元組
(1)消除取值重復的行
例10 查詢所有選修過課的學生的學號
SELECT Sno FROM SC;
假設SC表中有下列數據
Sno Cno Grade
------- ------- -------
95001 1 92
95001 2 85
95001 3 88
95002 2 90
95002 3 80
執行上面的SELECT語句後,結果為:
Sno
-------
95001
95001
95001
95002
95002
該查詢結果裡包含了許多重復的行。如果想去掉結果表中的重復行,必須指定DISTINCT短語:
SELECT DISTINCT Sno FROM SC;
執行結果為:
Sno
-------
95001
95002
(2)查詢滿足條件的元組
查詢滿足指定條件的元組可以通過WHERE子句實現。WHERE子句常用的查詢條件如表3-3所示。
常用的查詢條件
查詢條件 謂 詞
─────── ───────────────
比較(比較運算符) = 、>、>=、<、<=、<>(!=)、NOT
確定范圍 BETWEEN AND, NOT BETWEEN AND
確定集合 IN, NOT IN
字符匹配 LIKE, NOT LIKE
空值 IS NULL, IS NOT NULL
多重條件 AND, OR
①比較大小
例11 查詢計算機系全體學生的名單
SELECT Sname FROM Student WHERE Sdept = '計算機系';
例12 查詢所有年齡在20歲以下的學生姓名及其年齡
SELECT Sname, Sage FROM Student WHERE Sage <20;
或 SELECT Sname, Sage FROM Student WHERE NOT Sage>= 20;
例13查詢考試成績有不及格的學生的學號
SELECT DISTINCT Sno FROM Course WHERE Grade <60;
這裡使用了DISTINCT短語,當一個學生有多門課程不及格,他的學號也只列一次。
② 確定范圍
例14 查詢年齡在20至23歲之間的學生的姓名、系別、和年齡
SELECT Sname, Sdept, Sage FROM Student WHERE Sage BETWEEN 20 AND 23;
與BETWEEN...AND...相對的謂詞是NOT BETWEEN...AND...。
例15 查詢年齡不在20至23歲之間的學生姓名、系別和年齡
SELECT Sname, Sdept, Sage FROM Student WHERE Sage NOT BETWEEN 20 AND 23;
③確定集合
例16 查詢信息系、數學系和計算機系的學生的姓名和性別
SELECT Sname, Ssex FROM Student WHERE Sdept IN ('信息系', '數學系', '計算機系');
與IN相對的謂詞是NOT IN,用於查找屬性值不屬於指定集合的元組。
例17 查詢既不是信息系、數學系,也不是計算機科學系的學生的姓名和性別
SELECT Sname, Ssex FROM Student
WHERE Sdept NOT IN ('信息系', '數學系', '計算機系');
④字符匹配
謂詞LIKE可以用來進行字符串的匹配。其一般語法格式如下:
[NOT] LIKE '<匹配串>'其含義是查找指定的屬性列值與<匹配串>相匹配的元組。<匹配串>可以是一個完整的字符串,也可以含有以下通配符。
%(百分號) 代表任意長度(長度可以為0)的字符串。
_(下橫線) 代表任意單個字符。
[ ]:匹配[ ]中的任意一個字符。
[^]:不匹配[ ]中的任意一個字符。
例18 查所有姓劉的學生的姓名、學號和性別
SELECT Sname, Sno, Ssex FROM Student WHERE Sname LIKE '劉%';
例19 查名字中第二字為“大”或“小”的學生的姓名和學號
SELECT Sname, Sno FROM Student WHERE Sname LIKE '__[大小]%';
例20 查詢所不姓劉的學生姓名
SELECT Sname, Sno, Ssex FROM Student WHERE Sname NOT LIKE '劉%';
例21 查詢學號中最後一位不是2、3、5的學生情況
SELECT * FROM Student WHERE Sno LIKE ‘%[^235]’;
⑤ 涉及空值的查詢
例23 某些學生選修某門課程後沒有參加考試,所以有選課記錄,但沒有考試成績,下面我們來查一下缺少成績的學生的學號和相應的課程號
SELECT Sno, Cno FROM SC WHERE Grade IS NULL;
注意這裡的'IS'不能用等號('=') 代替。
例24 查所有有成績的記錄的學生學號和課程號
SELECT Sno, Cno FROM SC WHERE Grade IS NOT NULL;
⑥多重條件查詢
邏輯運算符AND和OR可用來聯結多個查詢條件。如果這兩個運算符同時出現在同一個WHERE條件子句中,則AND的優先級高於OR,但用戶可以用括號改變優先級。
例25 查詢計算機系年齡在20歲以下的學生姓名
SELECT Sname FROM Student WHERE Sdept='計算機系' AND Sage<20;
例12 中的IN謂詞實際上是多個OR運算符的縮寫,因此例12中的查詢也可以用OR運算符寫成如下等價形式:
SELECT Sname, Ssex FROM Student
WHERE Sdept='信息系' OR Sdept='數學系' OR Sdept='計算機系';
3.對查詢結果排序
如果沒有指定查詢結果的顯示順序,DBMS將按其最方便的順序(通常是元組在表中的先後順序)輸出查詢結果。用戶也可以用ORDER BY子句指定按照一個或多個屬性列的升序(ASC)或降序(DESC)重新排列查詢結果,其中升序ASC為缺省值。
例26 查詢選修了3號課程的學生的學號及其成績,查詢結果按分數的降序排列
SELECT Sno, Grade FROM SC WHERE Cno='3' ORDER BY Grade DESC;
前面已經提到,可能有些學生選修了3號課程後沒有參加考試,即成績列為空值。用ORDER BY子句對查詢結果按成績排序時,若按升序排,成績為空值的元組將最後顯示,若按降序排,成績為空值的元組將最先顯示。
例27 查詢全體學生情況,查詢結果按所在系升序排列,對同一系中的學生按年齡降序排列
SELECT * FROM Student ORDER BY Sdept, Sage DESC;
4.使用集函數
為了進一步方便用戶,增強檢索功能,SQL提供了許多集函數,主要包括:
COUNT([DISTINCT|ALL] *) 統計元組個數
COUNT([DISTINCT|ALL] <列名>) 統計一列中值的個數
SUM([DISTINCT|ALL] <列名>) 計算一列值的總和(此列必須是數值型)
AVG([DISTINCT|ALL] <列名>) 計算一列值的平均值(此列必須是數值型)
MAX([DISTINCT|ALL] <列名>) 求一列值中的最大值
MIN([DISTINCT|ALL] <列名>) 求一列值中的最小值
如果指定DISTINCT短語,則表示在計算時要取消指定列中的重復值。如果不指定DISTINCT短語或指定ALL短語(ALL為缺省值),則表示不取消重復值。
例29 查詢學生總人數
SELECT COUNT(*) FROM Student;
例30 查詢選修了課程的學生人數
SELECT COUNT(DISTINCT Sno) FROM SC;
學生每選修一門課,在SC中都有一條相應的記錄,而一個學生一般都要選修多門課程,為避免重復計算學生人數,必須在COUNT函數中用DISTINCT短語。
例31 計算1號課程的學生平均成績
SELECT AVG(Grade) FROM SC WHERE Cno='1';
例32 查詢選修1號課程的學生最高分數
SELECT MAX(Grade) FROM SC WHERE Cno='1';
例33 查詢選修1號課程的學生最高分、最低分及平均分
SELECT MAX(Grade),MIN(Grade),AVG(Grade) FROM SC WHERE Cno='1';
5.對查詢結果分組
GROUP BY子句可以將查詢結果表的各行按一列或多列取值相等的原則進行分組。
對查詢結果分組的目的是為了細化集函數的作用對象。如果未對查詢結果分組,集函數將作用於整個查詢結果,即整個查詢結果只有一個函數值。否則,集函數將作用於每一個組,即每一組都有一個函數值。
例34 查詢各個課程號與相應的選課人數
SELECT Cno, COUNT(Sno) FROM SC GROUP BY Cno;
該SELECT語句對SC表按Cno的取值進行分組,所有具有相同Cno值的元組為一組,然後對每一組作用集函數COUNT以求得該組的學生人數。查詢結果為:
Cno COUNT(Sno)
------ ----------
1 22
2 34
3 44
4 33
5 48
如果分組後還要求按一定的條件對這些組進行篩選,最終只輸出滿足指定條件的組,則可以使用HAVING短語指定篩選條件。
例35 查詢信息系選修了3門以上課程的學生的學號
SELECT Sno FROM SC WHERE Sdept=‘信息系’ GROUP BY Sno HAVING COUNT(*)>3;
選修課程超過3門的信息系學生的學號,首先需要通過WHERE子句從基本表中求出信息系的學生。然後求其中每個學生選修了幾門課,為此需要用GROUP BY子句按Sno進行分組,再用集函數COUNT對每一組計數。如果某一組的元組數目大於3,則表示此學生選修的課超過3門,應將他的學生號選出來。HAVING短語指定選擇組的條件,只有滿足條件(即元組個數>3)的組才會被選出來。
WHERE子句與HAVING短語的根本區別在於:作用對象不同,WHERE子句作用於基本表或視圖,從中選擇滿足條件的元組。HAVING短語作用於組,從中選擇滿足條件的組