一、連接查詢
1、等值於非等值連接查詢
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno;
學生情況存放在Student表中,學生選課情況存放在SC表中,所以本次查詢涉及Student和SC兩個表,這兩個表之間的聯繫是通過公共屬性Sno實現的。
查詢結果:
SELECT子句與WHERE子句的屬性名前都加上了表名前綴,這是爲了避免混淆。如果屬性名在參加連接的各表中是唯一的(連接的表裏只能一個表有!!!),則可以省略表名前綴。
在等值連接中,把目標列中重複的屬性列去掉爲自然連接。
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno=SC.Sno;
在本例中,由於Student.Sno,Sname,Ssex,Sage,Sdept,Cno和Grade屬性列在Student表和SC表中是唯一的,因此引用時可以去掉表名前綴,而Sno在兩個表中都出現了,因此引用時必須加上表名前綴。
查詢結果:這樣重複的Sno只留了一列。(不要care那個奇奇怪怪的S_entrance列)
一條SQL語句可以同時完成選擇和連接查詢,這時WHERE子句是由連接謂詞和選擇謂詞組成的複合條件。
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND
SC.Cno='2' AND SC.Grade>90;
我表裏沒有符合條件的人,所以不展示截圖了。(如果你忘了寫表名前綴的話,快接受批評!!!我可能是魚的記憶)
2、自身連接
連接操作不僅可以在兩個表之間進行,還可以一個表與其自已進行連接,成爲自身連接。
在Course表中只有每門課的直接先選課的信息,而沒有先修課的先修課。要得到這個信息,必須先對一門課找到其先修課,再按此先修課的課程號查找它的先修課程,這就要將Course與其自身連接。
爲此,要爲Course表取兩個別名,一個是FIRST,另一個是SECOND。
SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno=SECOND.Cno;
查詢結果:
3、外連接
例3.49中表裏沒有一些學生的信息,那是因爲他們沒有選課,在SC表中沒有相應的元組,導致Student中這些沒有選課的元組被捨棄了。
如果想即使沒有選課,仍把Student的懸浮元組保存在結果關係中,而在SC表的屬性上寫NULL,這時就要使用外連接!
改寫例3.49:
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUTER JOIN SC ON(Student.Sno=SC.Sno);
查詢結果:,這樣沒有選課的兩位同學也展示了出來。
左外連接列出左邊關係中所有的元組(本例),右外連接列出右邊關係中所有的元組。
4、多表連接
連接操作除了兩表連接,自身鏈接外,還可以兩個以上的表進行連接,稱爲多表連接。
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
查詢結果:
在執行多表連接時,通常是先進行兩個表的連接操作,再將其連接結果與第三個表進行連接。
二、嵌套查詢
①在SQL語言中,一個SELECT-FROM-WHERE語句稱爲一個查詢塊。將一個查詢塊嵌套在另一個查詢塊的WHERE子句或HAVING短語的條件中的查詢稱爲嵌套查詢。
②上層的查詢塊稱爲外層查詢或父查詢,下層的查詢塊稱爲內層查詢或子查詢。
③SQL語言允許多層嵌套查詢,及一個子查詢中還可以嵌套其他子查詢。但是子查詢的SELECT語句中不能使用ORDER BY子句,該子句只能對最終查詢結果排序。
1、帶有IN謂詞的子查詢
方法一(子查詢的查詢條件不依賴於父查詢,稱爲不相關子查詢):
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='劉晨');
方法二(由裏向外處理,先進性子查詢,子查詢的結果用於建立其父查詢的查找條件):
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN('CS');
方法三(用自身連接來完成):
SELECT S1.Sno,S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept=S2.Sdept AND S2.Sname='劉晨';
查詢結果都爲:
本題涉及了兩個表Student表和Course表,但這兩個表沒有直接聯繫,所以要通過SC表建立聯繫,所以實際上就涉及了三個表的查詢。
SELECT Sno,Sname
FROM Student
WHERE Sno IN
(SELECT Sno
FROM SC
WHERE Cno IN
(SELECT Cno
FROM Course
WHERE Cname='信息系統'
)
);
還可以用連接查詢:
SELECT Student.Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND
SC.Cno=Course.Cno AND
Course.Cname='信息系統';
查詢結果都爲:
但是有些嵌套查詢可以用連接查詢代替,有些就不可以。
2、帶有比較運算符的子查詢
帶有比較運算符的子查詢是指父查詢與子查詢之間用比較運算符進行連接。
SELECT Sno,Cno
FROM SC x
WHERE Grade>=(SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno);
x是表SC的別名,又稱元組變量,可以用來表示SC的一個元組。內層查詢是求一個學生所有選修課程平均成績的,至於是那個學生的平均成績要看參數x.Sno的值,而該值是與父查詢相關的,因此這類查詢稱爲相關子查詢。
查詢結果:
3、帶有ANY(SOME)或ALL謂詞的子查詢
SELECT Sname,Sage
FROM Student
WHERE Sage<ANY(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
查詢結果:
SELECT Sname,Sage
FROM Student
WHERE Sage<ALL
(SELECT Sage
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
查詢結果:
這兩個例子查詢都可以用聚集函數來實現。
比如例3.59用聚集函數表示爲:
SELECT Sname,Sage
FROM Student
WHERE Sage<
(SELECT Min(Sage)
FROM Student
WHERE Sdept='CS')
AND Sdept<>'CS';
查詢結果相同。