深入理解數據庫select語句

這篇博客帶領大家發現數據庫 select 語句背後的實現步驟。首先創建三個表,分別是 Student (學生信息表)、Course (課程信息表)、SC (學生選課信息表)

其中,Course 表中,Cpno 是外碼,被參照表是Course,被參照列是 Cno;SC 表中,Sno 參照 Student 中的Sno,Cno參照Course 中的 Cno 。

下面從簡單的 select 語句到複雜的 select 語句進行分析。

select Sno, Sname    
from Student;

1. 這個是最基本的 select 語句查詢

具體查詢步驟如下:

(1) 從 Student 中取出一個元組

(2)取出該元組在 Sno 和 Sname 上的值

(3) 形成一個新的元組進行輸出

(4) 完成一個元組的輸出後,對 Student 表中剩餘的所有元組做相同操作

得到的結果如圖       

2. 含有 where 語句的最基本查詢

例如:查找計算機系全體學生的名單

select Sname
from Student
where Sdept='CS';

具體步驟如下:

(1) 對 Student 進行全表掃描,取出一個元組

(2) 檢查該元組在Sdept 列的值是否等於 ’CS' 

(3) 若相等,則取出 Sname 列的值形成一個新元組輸出;否則跳過取下一元組

(4) 對 Student 表中的所有元組做相同操作

下面對 where 語句的用法進i行一些舉例(不完全)

1. 查詢所有年齡在20歲以下的學生年齡及其姓名
    select Sname, Sno
    from Student
    where Sage < 20;     //比較謂詞 <

2. 查詢年齡在 20~23 歲之間的學生的姓名、系別、年齡
    select Sname, Sdept, Sage
    from Student
    where Sage BETWEEN 20 TO 23;   //確定範圍謂詞 BETWEEN 下限 TO 上限 ,NOT BETREEN XX TO XX

3. 查詢計算機科學系(CS)、數學系(MA)和信息系(IS)學生的姓名和性別
    select Sname, Ssex
    from Student
    where Sdept IN ('CS', 'MA', 'IS');  //確定集合謂詞 IN、NOT IN

4. 查詢名字中第二個字爲“陽”的學生的姓名和學號
    select Sname, Sno
    from Student
    where Sname LIKE '_陽%';  //字符匹配謂詞 LIKE、NOT LIKE

5. 查詢成績爲空的學生的學號和課程號
    select Sno, Cno
    from SC
    where Grade IS NULL;    //空值謂詞 IS NULL、IS NOT NULL

6. 查詢計算機科學系年齡在20歲以下的學生姓名
    select Sname
    from Student
    where Sdept='CS' AND Sage<20;  //多重條件謂詞 AND, OR, NOT

3. group by 與 having 語句

例如:查詢平均成績大於等於 80 分的學生學號和平均成績。

SELECT Sno,AVG(Grade) average
FROM SC 
GROUP BY Sno
HAVING AVG(Grade)>=80;

(1) 對 Student 進行全表掃描,取出一個元組

(2) 根據 GROUP BY 子句按 Sno進行分組,得到以下表格

(3) 再用聚集函數AVG(Grade) 對每一組進行計數,HAVING 函數給出選擇組的條件,只有滿足條件的元組,纔會被選擇出來。

注意,此處由於數據源太小,導致(2)和(3)選出來的元組相同,但是,如果足夠大的話,在(2)中只有滿足條件的元組纔會被選擇出來。

4. 連接查詢

連接查詢分爲 等值與非等值連接查詢、自身連接、外連接和多表連接。連接時內部的步驟都是大同小異,所以這裏只舉自身連接的例子。

例如:查詢每一門棵的簡介先修課。

SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno=SECOND.Cno;

我本人在剛開始學語句的時候,一直不確定,FIRST 和 SECOND 我還沒有定義呢,計算機可以識別嗎?雖然我還沒有查官方資料,但是姑且可以這樣理解。上面我們知道,select 進行最基本的單表查詢的時候,先是確定尋找的作用域,根據 where 語句篩選相關元組,最後再將元組中需要顯示的列進行顯示。由此我們可以看到,select 語句時最後才發揮作用的。

步驟如下:

(1) 從FIRST(Course)中找到第一個元組

(2) 從頭開始掃描 SECOND(Course)

(3) 逐一查找與FIRST 中Cpno 相同的 Cno (笛卡爾積)

(4) 找到後將FIRST 的Cno與該元組的 Cpno 拼接起來,形成一個元組

(5) SECOND 全部查找完後,再查找 FIRST 的第二個元組,直至 FIRST 中的元組全部處理完畢。

5. 嵌套查詢

不相關子查詢的步驟很簡單,找到子查詢的結果,再找父查詢的結果就可以了。講講相關子查詢吧。

例如:找到每個學生超過他自己選修課程平均成績的課程號。

SELECT Sno,Cno
FROM SC X
where Grade >= 
	(SELECT AVG(Grade)
	 FROM SC Y
	 where Y.Sno=X.Sno);

步驟如下:

(1) 從外層查詢中取到SC的一個元組x ,將元組 x 的Sno 值(201215121)傳給內層循環:

SELECT AVG(Grade)
FROM SC Y
where Y.Sno='201215121'

(2) 執行內層查詢,得到值 88(近似值),用該值代替內層查詢,得到外層查詢:

SELECT Sno,Cno
FROM SC X
where Grade >= 88

(3) 執行這個查詢,得到:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章