子查詢
子查詢是嵌套的 SELECT 查詢,也就是就是在某個 SELECT 結果集中進行檢索。子查詢能夠將比較復雜的查詢分解為幾個簡單的查詢,而且子查詢可以嵌套。嵌套查詢時先執行內部檢查再執行外部查詢,內部查詢的結果將傳遞給外層語句,並作為外層語句的查詢條件來使用。需要指出子查詢是多表查詢的特殊情況,並不能替代多表查詢。
子查詢語法
任何允許使用表達式的地方都可以使用子查詢,使用子查詢的 SELECT 語句的一般格式如下。
SELECT 列名列表
FROM 表名1
WHERE 列名1 運算符
(
SELECT 列名1
FROM 表名2
WHERE 列名2 運算符
(
SELECT 列名2
FROM 表名3
WHERE 條件
)
)
查詢樣例
樣例一
假設 Student 表中有如下一些數據:
查詢與“王麗娜”同班的學生學號、姓名,可以在 WHERE 使用子查詢查出班級作為過濾條件。
SELECT SNO, Sname FROM Student
WHERE CLASS = (SELECT CLASS FROM Student WHERE SNAME = '王麗娜')
樣例二
查詢和學號為 101 的同學同月出生的所有學生的 Sno、Sname 和列,使用子查詢查出月份作為過濾條件。
SELECT Sno, Sname, Sbirthday FROM Student
WHERE MONTH(Sbirthday) = (SELECT MONTH(Sbirthday) FROM Student WHERE Sno = '101')
樣例三
查詢每人的成績(學號、課程號、成績)和本課程平均分,本課程平均分可以用和自己連接的子查詢查出。
SELECT Sno, Cno, Degree,
(SELECT AVG(Degree) FROM Score sc2 WHERE sc1.Cno = sc2.Cno) 科平均
FROM Score sc1
樣例四
假設此時有成績表 Course,表中具有以下字段和記錄。
查詢每人的成績(學號、姓名、課程名、成績)和本班本科平均分,本班本科平均分可以用子查詢實現。
SELECT SC.Sno, S.Sname, SC.Cno, C.Cname, SC.Degree,
(
SELECT AVG(Degree)
FROM Score SC2
JOIN Student S2 ON SC2.Sno = S2.Sno
JOIN Course C2 ON SC2.Cno = C2.Cno
WHERE S.Sname = S2.Sname AND SC.Cno = C2.Cno
) 班科平均
FROM Score SC
JOIN Student S ON SC.Sno = S.Sno
JOIN Course C ON SC.Cno = C.Cno
EXISTS 嵌套子查詢
EXISTS 子句
EXISTS 和 NOT EXISTS 子句通常和相關子查詢一起使用,可以限制外層查詢,使其結果集符合子查詢的條件,並可以判斷某個值是否存在於一系列的值中。
查詢樣例
樣例一
當分數表中存在與學生表中相同的學號,查詢其學號和姓名。
SELECT Sno, Sname
FROM Student S
WHERE EXISTS (SELECT * FROM Score WHERE Sno = S.Sno)
樣例二
查詢沒有成績同學的姓名和學號,使用 NOT EXISTS 子句實現。
SELECT SNO, SNAME
FROM Student S
WHERE NOT EXISTS (SELECT * FROM Score WHERE Sno = S.Sno)
集合運算
集合運算操作符
可以使用如下操作符,對 2 個 SELECT 結果集進行集合運算。
關鍵字 | 功能 |
---|---|
UNION | 對 2 個結果集做並集運算 |
INTERSECT | 對 2 個結果集做交集運算 |
EXCEPT | 對 2 個結果集做差集運算 |
查詢樣例
樣例一
假設此時有教師表 Teacher,表中具有以下字段和記錄。
將教師表和學生表匯總為一個表,使用 UNION 做並集運算。
SELECT Tname, Tsex FROM Teacher
UNION
SELECT Sname, Ssex FROM Student
樣例二
查詢學生表中小於 108 且大於 103 的所有學生信息,使用 INTERSECT 做交集運算。
SELECT * FROM Student WHERE Sno < '108'
INTERSECT
SELECT * FROM Student WHERE Sno > '103'
樣例三
查詢學生表中小於 108 但不大於 103 的所有學生信息,使用 EXCEPT 做差集運算。
SELECT * FROM Student WHERE Sno < '108'
EXCEPT
SELECT * FROM Student WHERE Sno > '103'
ALL、ANY 和 SOME
ALL、ANY 和 SOME 的功能
ALL 是所有,表示全部都滿足才返回 true。ANY(SOME)是任意一個,表示有任何一個滿足就返回 true。"=ANY"與"IN"相同,"<>ALL"與"NOT IN"相同。
查詢樣例
樣例一
查詢所以成績都及格的學生的信息(學號,姓名,課程號,課程名,成績,最低成績),可以先使用子查詢查出某位同學的所有成績,再結合 ALL 運算符作為過濾條件。
SELECT SC.Sno, S.Sname, C.Cname, SC.Degree,
(SELECT MIN(Degree) FROM Score SC2 WHERE SC.Sno = SC2.Sno) 最低分
FROM Score SC
JOIN Student S ON SC.Sno = S.Sno
JOIN Course C ON SC.Cno = C.Cno
WHERE 60 < ALL(
SELECT Degree FROM Score010 SC3
WHERE SC3.Sno = SC.Sno
)
樣例二
查詢成績有不及格的學生的信息(學號,姓名,課程號,課程名,成績, 最低成績)可以先使用子查詢查出某位同學的所有成績,再結合 ANY 運算符作為過濾條件。
SELECT SC.Sno, S.Sname, C.Cname, SC.Degree,
(SELECT MIN(Degree) FROM Score SC2 WHERE SC.Sno = SC2.Sno) 最低分
FROM Score SC
JOIN Student S ON SC.Sno = S.Sno
JOIN Course C ON SC.Cno = C.Cno
WHERE 60 > ANY(
SELECT Degree FROM Score SC3
WHERE SC3.Sno = SC.Sno
)
參考資料
《SqlServer 2014 數據庫技術實用教程》,胡伏湘、肖玉朝 主編,清華大學出版社