一、SQL語言查詢選修了全部課程的學生的學號和姓名。
兩種解決途徑:
第一種:
我們可以表示為在SC表中某個學生選修的課程數等於C表中課程總數。相應的SQL語言如下:
select S#,SNAME from S where S# in (select S# from SC group by S# --根據Sno分組,統計每個學生選修了幾門課程。如果等於C表課程的總數,就是我們要找的S# having count(*) = (select count(*) from C))--統計C表中共有幾門課程
第二種:
問題:查詢選修了全部課程的學生的學號和姓名。
可以轉換為:查詢沒有一門課沒有被該生選擇的學生的學號和姓名。
相應的SQL語言如下:
select S#,SNAME -- 在 S 表里選 S#,SNAME from S where not exists -- 不存在 (select * -- 課程 from C where not exists -- 沒有 (select * -- 被該生選擇的課程 from SC where SC.S#=S.S# and SC.C#=C.C#)) -- 相關查詢,三個表進行連接
這個查詢語句可以這樣理解:
查詢沒有一門課沒有被該生選擇的學生的學號和姓名。
第一個select 必定是在 S 表里選 S#,SNAME
select S#,SNAME
from S
where (不存在)
第二個select 是課程,來自C表)
select *
from C
where (沒有)
第三個select是課程被該生選擇,來自SC表)
select *
from SC
where (SC學號對應S表學號,SC表課程號對應C表課程號)
二、SQL語言查詢選修了學號為“2001050105”的學生所選全部課程的學生姓名。
問題:查詢選修了學號為“2001050105”的學生所選全部課程的學生姓名。
可以轉換為:查詢沒有一門課(被學號“2001050105”的學生選擇的課)沒有被該生選擇的學生的姓名。
相應的SQL語言如下:
select St_Name -- 從st_info表中選擇姓名 from st_info where not exists -- 不存在 (select * --被學號為‘2001050105’的學生選擇的課程 from s_c_info as sc_1 where st_id='2001050105' and not exists --沒有 (select * --被該生選擇 from s_c_info as sc_2 where sc_2.st_id=st_info.St_ID and sc_2.c_no=sc_1.c_no))
這個查詢語句可以這樣理解:
查詢沒有一門課(被學號“2001050105”的學生選擇的課)沒有被該生選擇的學生的姓名。
第一個select從st_info 中選出St_name
select St_Name
from st_info
where (不存在)
第二個select 是從s_c_info表中選出學號為“2001050105”的學生選擇的課程
select *
from s_c_info as sc_1
where st_id='2001050105' and (不存在)
第三個select是從s_c_info表中選出課程被該生選擇的記錄
select *
from s_c_info as sc_2
where(sc_2學號對應st_info學號,sc_2表課程號對應sc_1表的課程號)
之所以起別名sc_1和sc_2主要是他們來自同一個表,但是我們首先是從s_c_info表中選出了學號為“2001050105”的學生的選修記錄並放到了sc_1中,這樣在最后關聯的時候就可以直接關聯。
三、總結:
上述兩個問題,其實解題思維是一樣的,都是運用了兩次 not exists 雙重否定表示肯定,理解了這兩個問題,在遇到相似的問題,可以進行相應的轉化。那么該問題既然是雙重否定,那么可不可以用兩個 exists 呢?顯然不可以。自己思考一下吧。如果理解了上述問題,很簡單的就可以知道原因。