1. 程式人生 > >第8講:復雜查詢

第8講:復雜查詢

基本語法 pan ont 子句 not 題目 循環 教師 三種

一、子查詢概述

1. 子查詢定義

①出現在where子句中的select語句被稱為子查詢,即在where子句中嵌套一個select-from-where

②子查詢返回一個集合,可以通過與這個集合比較來確定另一個查詢集合

2. 三種類型的子查詢

  • (not) in子查詢
  • θ some/θ all子查詢
  • (not) exists子查詢

3. 帶有子查詢的select語句區分為內層查詢和外層查詢(內層查詢被嵌入到外層查詢中)

技術分享圖片

①非相關子查詢:內層查詢獨立進行,沒有涉及任何外層查詢相關信息的子查詢

②相關子查詢:內層查詢需要依靠外層查詢的某些參量作為限定條件才能進行

  • 外層向內層傳遞的參量需要使用外層的表名或表別名來限定
  • 相關子查詢只能由外層向內層傳遞參數,這也稱為變量的作用域規則

【示例】求學過001號課程的學生的姓名:

  • select Sname from Student Stud where S# in (select S# from SC where C# = ‘001‘ and S# = Stud.S#);
  • 參量S#表示內層查詢的S#必須在Student表中也出現過

4. 子查詢是為了判斷下列條件,它們分別對應了in、θ some/θ all、exists子查詢

(1)集合成員資格:某一元素是否是某一個集合的成員

(2)集合之間的比較:某一個集合是否包含另一個集合等

(3)集合基數的測試:測試集合是否為空

二、(not) in子查詢

1. 基本語法形式:表達式 [not] in (子查詢)

①語義:判斷表達式的值是否在子查詢的結果(一個集合)

【示例1】列出張三、王三同學的所有信息:

  • select * from Student where Sname in (‘張三‘, ‘王三‘); // 該處直接使用了某一子查詢的結果(集合)

【示例2】列出選修了001號課程的學生的學號和姓名:

  • selsect S#, Sname from Student where S# in
    (select S# from SC where C# = ‘001‘);
  • 子查詢返回學過001號課程的學生的學號(集合),如果某學號在該集合中,就表示該學生學過001號課程,也就是要找的

【示例3】求既學過001號課程,又學過002號課程的學生的學號:

  • select S# from SC where C# = ‘001‘ and S# in (select S# from SC where C# = ‘002‘);
  • 子查詢返回學過002號課程的學生的學號(集合),如果某學號在該集合中,就表示該學生學過002號課程

【示例4】列出沒學過李明老師講授課程的學生的姓名:

  • select Sname from Student where S# not in (selsect S# from SC, Course C, Teacher T where SC.C# = C.C# and C.T# = T.T# and T.Tname = ‘李明‘);
  • 子查詢返回學過李明老師講授課程的學生的學號(集合),如果某學號不在該集合中,就表示該學生沒學過李明老師的課

三、θ some/θ all子查詢

1. 基本語法形式:表達式 θ some/all (子查詢)

①θ是比較運算符,可以為<、>、<=、>=、=、<>

②語義:將表達式的值與子查詢的結果(一個集合)進行比較

  • “表達式 θ some (子查詢)”的結果為真:表達式的值至少與子查詢結果(集合)中的某一個值相比較滿足θ關系
  • “表達式 θ all (子查詢)”的結果為真:表達式的值與子查詢結果(集合)中的所有值相比較都滿足θ關系

【示例1】找出工資最低的教師的姓名:

  • select Tname from Teacher where Salary <= all (select Salary from Teacher);
  • 子查詢返回所有教師的工資(集合),當某工資小於等於該集合中的所有工資時,則表示該教師工資最低

【示例2】找出001號課成績不是第一的所有學生的學號:

  • select S# from SC where C# = ‘001‘ and Score < some (select Score from SC where C# = ‘001‘);
  • 子查詢返回學過001號課的學生的成績(集合),如果某成績小於該集合中的某一個工資時,則表示該學生成績不是第一

【示例3】找出001號課成績最高的所有學生的學號:

  • select S# from SC where C# = ‘001‘ and Score >= all (select Score from SC where C# = ‘001‘);

【示例4】找出98030101號學生成績最低的課程號:

  • select C# from SC where S# = ‘98030101‘ and Score <= all (select Score from SC where S# = ‘98030101‘);

【示例5】找出張三同學成績最低的課程號(相關子查詢):

  • select C# from SC, Student Stud where SC.S# = Stud.S# and Sname = ‘張三‘ and Score <= all (select Score from SC where S# = Stud.S#);
  • 涉及到姓名,即涉及到Student表,子查詢返回該學生的所有成績
  • 此處相關子查詢中,內層循環需要借助外層循環的Stud來限定S#為張三的S#

四、(not) exists子查詢

1. 基本語法形式:[not] exists (子查詢)

①語義:判斷子查詢的結果(一個集合)中是否存在元組

②註:本子查詢較難理解,應註意轉換題目意思,然後從“不存在...不存在”這一語義進行解題。

【示例1】檢索學過001號教師教的所有課程的所有學生的姓名:

  • select Sname from Student where not exists (select * from Course where T# = ‘001‘ and not exists (select * from SC where S# = Student.S# and C# = Course.C#));
  • 題目語句的意思等價於“不存在有一門001號教師教的課程該同學沒學過”

【示例2】列出沒學過李明老師講授任何一門課程的所有學生的姓名:

  • select Sname from Student where not exists (select * from Course, SC, Teacher where Tname = ‘李明‘ and Course.T# = Teacher.T# and Course.C# = SC.C# and S# = Student.S#);

【示例3】列出至少學過98030101號同學學過所有課程的同學的學號:

  • select DISTINCT S# from SC SC1 where not exists (select * from SC SC2 where SC2.S# = ‘98030101‘ and not exists (select * from SC where C# = SC2.C# and S# = SC1.S#));

第8講:復雜查詢