1. 程式人生 > >SQL中的連線查詢與巢狀查詢

SQL中的連線查詢與巢狀查詢

連線查詢

若一個查詢同時涉及兩個或兩個以上的表,則稱之為連線查詢。連線查詢是資料庫中最最要的查詢, 包括: 1、等值連線查詢 2、自然連線查詢 3、非等值連線查詢 4、自身連線查詢 5、外連線查詢 6、複合條件查詢 等值與非等值連線查詢: 比較運算子主要有=、>、<、>=、<=、!=(或<>)等。 下面來看一個例子: 假設有一個學生資料庫,其中有三張表,即學生資訊表(Student)、課程表(Course)、選課表(Study),三張表中的資訊如下:


例1:要求查詢選修了課程的學生的資訊 很顯然,需要用連線查詢,學生的情況存放在student表中,學生的選課情況存放在Study表中,所以查詢實際涉及Student和Study這兩個表。這兩個表之間的聯絡是通過公共屬性Sno實現的。 考慮下列等值連線查詢語句
SELECT Student.*,Study.*
FEOM Student,Study
WHERE Student.Sno=Study.Sno				/*將Student與Study中同一學生的元祖連線起來*/

得到的結果:
我們發現,上述查詢語句按照把兩個表中學號相等的元祖連線起來。 系統執行的連線過程:首先在表Student中找到一個元祖,然後從頭開始掃描Study表,逐一查詢與Student第一個元祖的Sno相等的元祖,找到後就將Student表中的第一個元祖與該元祖拼接起來,形成結果表中的一個元祖,Stdudy表全部查詢完後,再找Student中的第二個元祖,重複上述過程,直至Student表中的全部元祖處理完。 自然連線:在等值連線中把目標中重複的屬性列去掉的連線查詢 下面考慮用自然連線實現上述例子:
SELECT Student.Sno,SName,SSex,Sdept,Cno,Grade
FROM Student,Study
WHERE Student.Sno=Study.Sno
結果:
自身連線查詢:當查詢的結果涉及同一個表中兩個或以上的列時,考慮用自身連線查詢 例2:查詢每一門課的間接先行課(即先行課)
SELECT C1.Cpno
FEOM Course AS C1,Course AS C2		--為Course表起兩個別名C1、C2
WHERE C1.Pcno=C2.Cno				--兩個Course表的連線

查詢結果: 外連線查詢: 分為左外連線,右外連線, 左外連線:根據左表的記錄,在被連線的右表中找出符合條件的記錄與之匹配找不到匹配的,用null填充      右連線:根據右表的記錄,在被連線的左表中找出符合條件的記錄與之匹配,找不到匹配的,用null填充
例3:查詢缺少成績的的學生號和課程號
SELECT Student.Sno,Cno
FROM Student
LEFT JOIN Study
ON Student.Sno=Study.Sno
WHERE Grade IS NULL


例4:查詢所有學生的學號姓名、成績 --左外連線
SELECT Student.Sno AS 學號,SName AS 姓名, Grade AS 成績
FROM Student
LEFT JOIN Study
ON Student.Sno=Study.Sno
相當於: --右外連線
SELECT Student.Sno AS 學號,SName AS 姓名, Grade AS 成績
FROM Study 
RIGHT JOIN Student
ON Study.Sno=Student.Sno

左外連線列出左邊關係,右外連線列出右外關係中所有的元祖 多表連線查詢:
--1、WHRER 語句
--2、INNER JOIN.. 語句
例:查詢選修了C601號課程的學生姓名、分數、課程名 這個查詢三個涉及了表學生表、課程表和學習表’

SELECT Student.SName AS 學生姓名,Grade AS 成績,CName AS 課程名
FROM Student
INNER JOIN Study ON Student.Sno=Study.Sno
INNER JOIN Course ON Study.Cno=Course.Cno
WHERE Course.Cno='C601'
相當於自然連線查詢:
SELECT Student.SName AS 學生姓名,Grade AS 成績,CName AS 課程名
FROM Student,Course,Study
WHERE Student=Study.Sno AND Study.cno=Course.Cno ADN Course.Cno=C601

巢狀查詢

巢狀查詢又稱子查詢,是指在父查詢的where條件語句中再插入一個子查詢語句,連線查詢都可以用子查詢完成,反之不然。 例1:找出至少一門課程的成績在90分以上的女學生的姓名 分析:已知的是分數大於90分這個條件,通過這個條件找出Study表中大於90分所對應的Sno,再通過連線查詢Study表中對應Sno的SName
SELECT SName
FROM Student
WHERE  Sex='女' AND Sno NOT IN
(
	SELECT Sno
	FROM Stduy
	WHERE Grade<90
)
注意:這裡子查詢返回的Sno可能有多個,所以要用到謂詞 IN,如果用 =,則報錯,因為 = 表示子查詢的返回值是唯一的。
子查詢的一個原則:根據已知得出未知 例2:查詢選修了課程名為 ‘’高等數學” 的學生學號和姓名 根據Course表中的高等數學得到課程號,再在Study表中找到選修了該課程號的學號,最後根據學號Sno在Student表中找出對應的學生的姓名。一層層巢狀,由已知得到未知。
SELECT Sno,SName
FROM Student
WHERE Sno IN
(
	SELECT Sno 
	FROM Study
	WHERE Cno IN
	(
		SELECT Cno 
		FROM Course
		WHERE CName='高等數學'
	)
)
相當於連線查詢:
SELECT Student.Sno,SName
FROM Student,Course,Study
WHERE Student.Sno=Study.Sno AND Course.Cno=Study.Cno AND Course.CName='高等數學'
查詢結果:
例3:找出至少學了C601和C602兩門課程的學生姓名。
這裡涉及到兩門課程,都來自Course表,涉及到同一個表中兩個或以上的元祖,考慮子查詢用自身連,子查詢根據課程號返回學號,父查詢再根據學號查詢姓名。
SELECT SName FROM Student
WHERE Sno IN
(
	SELECT Study1.Sno
	FROM Study AS Study1
	JOIN Study AS Study2
	ON Study1.Sno=Study2.Sno
	WHERE Study1.Cno='C601' AND Study2.Cno='C602'
)