SQL基礎查詢語句詳解

基本表的創建

3.3.2 定義基本表
3.5 建立一個“學生”表Student

Create table Student(
	Sno char(9) primary key,/* 列級完整性約束條件,Sno是主碼 */
	Sname char(20) unique, /* Sname	取唯一值 */
	Ssex char(2),
	Sage smallint,
	Sdept char(20) 
);

3.6 建立“課程”表Course

Create table Course(
	Cno char(4) primary key,/* Cno是主碼 */
	Cpno char(4),/* 先修課 */
	Ccredit smallint,
	foreign key(Cpno) references Course(Cno)
	/*表級完整性約束條件,Cpno是外碼,被參照表是Course,被參照列是Cno*/
);

3.7 建立學生選課表SC

Create table SC(
	Sno char(9),
	Cno char(4),
	Grade smallint,
	primary key (Sno,Cno),/*主碼由兩個屬性構成,必須作爲表級完整性進行定義*/
	foreign key(Sno) references Student(Sno),
	/*表級完整性約束條件,Sno是外碼,被參照表是Student*/
	foreign key(Cno) references Course(Cno)
	/*表級完整性約束條件,Sno是外碼,被參照表是Student*/
);

查詢語句詳細介紹

單表查詢

選擇表中的若干列

【3.16】查詢全體學生的學號與姓名

select Sno, Sname
from Student;

【3.18 】查詢全體學生的詳細記錄

select * from Student;

【3.20 】查詢全體學生的姓名、出生年份和所在院系,要求用小寫字母表示系名

select Sname,Year of Birth:’,2014-Sage,LOWER(Sdept)
from Student;

用戶可以通過指定別名來改變查詢結果的列標題,這對於含算術表達式、常量、函數名的目標列表達式尤其有用。3.20:

Select Sname NAME,Year of Birth:’ BIRTH,2014-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT
from Student;

選擇表中的若干元組

消除重複的行:使用distinct消除相同的行
【3.21】查詢選修了課程的學生學號

Select distinct Sno from SC;

【3.22】查詢滿足條件的元組:查詢計算機科學系全體學生名單

Select Sname from Student 
where Sdept=‘CS’;

【3.24】查詢考試成績不及格的學生學號

Select distinct Sno
from SC where Grade<60;

這裏使用了distinct,當一個學生有多門成績不合格,他的學號也只會出現一次
【3.26】查詢年齡不再20~23歲之間的學生姓名、系別和性別

Select Sname,Sdept,Sage
from Student 
where Sage not between 20 and 23;

【3.28】查詢既不是計算機科學系(CS)、數學系(MA),也不是信息系(IS)學生姓名和性別

Select Sname,Sdept,Sage
from Student
where Sdept not in(‘CS’,’MA’,IS);

通配符%和_:
% 代表任意長度(可以爲0)的字符串。
_代表任意單個字符。
【3.30】查詢所有姓劉的學生的姓名、學號、性別

Select Sname,Sno,Ssex
from Student
where Sname like ‘劉%;

【3.31】查詢姓“歐陽”且全名爲三個漢字的學生姓名

Select Sname
From Student
where Sname like ‘歐陽_’;

【3.32】查詢名字第二個字爲“陽”的學生學號和姓名

Select Sname,Sno
from Student
where Sname like’_陽%;

如果用戶要查詢的字符串本身就含有通配符%或_,就需要escape ’<換碼字符>’短語對通配符進行轉義
【3.34】查詢DB_Design課程的課程號和學分

Select Cno,Ccredit
from Course
where Cname like ‘DB\_Design’ escape’\’;

【3.35】查詢以“DB_”開頭,且倒數第三個字符爲i的課程的詳細情況

Select * from Course
where Cname like ‘DB\_%i__’ escape ‘\’;

【3.36】查詢缺少考試成績的學生的學號和相應的課程號

Select Sno,Cno from SC
where Grade is null;

多重條件查詢:默認情況下,and的優先級高於or,但是用戶可以通過括號改變優先級。
【3.38】計算機科學系年齡在20歲以下的學生姓名

Select Sname from Student
where Sdept=‘CS’ and Sage<20;

Order by 子句

默認爲ASC,可選爲DESC。對於空值,排序時顯示的次序由具體系統實現來決定。
【3.40】查詢全體學生情況,查詢結果按所在系號升序排列,同一系中的學生按年齡降序排列。

Select * from Student
order by Sdept,Sage desc;

聚集函數

sql提供了許多聚集函數,主要有:

Count(*)						
Count([distinct|all]<col name>) 
Sum([distinct|all]<col name>)	
avg([distinct|all]<col name>)	
max([distinct|all]<col name>)
min([distinct|all]<col name>)

當聚集函數遇到空值時,除了count(*)外,都跳過空值而只處理非空值。
where子句中是不能用聚集函數作爲條件表達式的,聚集函數只能用於select子句和group by中的having子句

【3.42】查詢選修了課程的學生人數

Select count(distinct Sno) from SC;

【3.44】查詢選修1號課程的學生的最高分數

Select max(Grade) from SC
where Cno=1;

【3.45】查詢學生2018001選修課程的總學分數

Select sum(Ccredit) from SC,Course
where Sno=2018001and SC.Cno=Course.Cno;

group by子句

【3.46】 求各個課程號及相應的選課人數

Select Cno,count(Sno)
from SC
group by Cno;

【3.47】查詢選修了三門以上課程的學生學號

Select Sno from SC
group by Sno
having count(*) > 3;

Where子句與having短語的區別在於作用的對象不同。where子句作用於基本表或視圖,從中選擇滿足條件的元組。having短語作用於組,從中選擇滿足條件的組。
【3.48】查詢平均成績大雨等於90分的學生學號和平均成績
下面的語句是不對的 =>

select Sno,AVG(Grade) from SC
where AVG(Grade)>=90
group by Sno;

因爲where子句是不能用聚集函數作爲條件表達式的,應該將其改爲having:

select Sno,AVG(Grade) from SC
group by Sno
Having AVG(Grade)>=90;

連接查詢

  1. 等值與非等值連接查詢
    【3.49】查詢每個學生及其選修課程的情況
Select Student.*, SC.*
from Student, SC
where Student.Sno=SC.Sno;
/*將Student與SC中同一學生的元組連接起來*/

關係型數據庫管理系統執行該連接操作的一種可能過程是:首先在表Student中找到第一個元組,然後從頭開始掃描SC表,逐一查找與Student第一個元組的Sno相等的SC元組,找到後將這兩個元組拼接起來,形成結果表中的一個元組。SC全部查找完後,再從Student找第二個元組……直到Student全部元組都處理完畢。這就是嵌套循環連接算法的基本思想

可以在SC表Sno上建立了索引,根據Sno值通過索引找到相對應的SC元組。在等值連接中把目標列中重複的屬性列去掉則爲自然連接
【3.50】對【3.49】用自然連接完成

Select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
from Student,SC
where Student.Sno=SC.Sno;

本例中,由於Sname,Ssex,Sage,Sdept,Cno和Grade屬性列在Student表與SC表中是唯一的,所以引用時可以去掉表名前綴;而Sno在兩個表中都出現了,因此引用必須加上表名前綴。

一條SQL語句可以同時完成選擇和連接查詢,這時where子句是由連接謂語和選擇謂語組成的複合條件。
【3.51】查詢選修2號課程且成績在90分以上的所有學生的學號和姓名

Select Student.Sno, Sname
from Student,SC
where Student.Sno=SC.Sno and/*連接謂語*/
	SC.Cno=2and SC.Grade>90;/*其他限定條件*/

該查詢的一種優化執行過程是,先從SC中挑選出Cno=‘2’並且Grade>90的元組形成一箇中間關係,再和Student中滿足連接條件的元組進行連接的到最終的結果關係。

  1. 自身連接
    【3.52】查詢每一門課程的間接先修課(即先修課的先修課)。
    在Course表中只有每門課的直接先修課信息,而沒有先修課的先修課,要得到這個信息,必須先對一門課找到其先修課,再按此先修課的課程號查找它的先修課程。這就要將Course表與自身連接。一個表與其自己進行連接,稱爲表的自身連接
    爲此,要爲Course表取兩個別名,一個是FIRST,一個是SECOND。
Select FIRST.Cno,SECOND.Cpno
from Course FIRST,Course SECOND
where FIRST.Cpno = SECOND.Cno;
  1. 外連接
    在通常的連接操作中,只有滿足連接條件的元組才能作爲結果輸出。如果學生沒有選課,在SC表中沒有相應的元組,那麼Student中這些元組在連接時就被捨棄了。

有時想以Student表爲主體列出每個學生的基本情況及其選課情況。若某個學生沒有選課,仍把Student的懸浮元組保存在結果關係。而在SC表的屬性上填空值NULL,這時候需要使用外連接

【3.53】

Select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
from Student 
left outer join SC on (Student.Sno=SC.Sno);
/* 
也可以使用USING來去掉結果中的重複值:
From Student left outer join SC using(Sno);
*/

左外連接列出左邊關係(如本例中Student)中所有的元組,右外連接列出右邊關係中所有的元組。

  1. 多表連接
    連接操作中除了可以是兩表連接、一個表與其自身連接,還可以是多表連接
    【3.54】查詢每個學生的學號、姓名、選修的課程名及成績
select Student.Sno,Sname,Cname,Grade
from Student,SC,Course
where Student.SNo=SC.Sno and SC.Cno=Course.Cno;

關係數據庫管理系統執行多表連接時,通常是先進行兩個表的連接操作,再將其連接結果與第三個表進行連接。本例的一個可能的執行方式是,先將Student表與SC表進行連接,的到每個學生的學號、姓名、所選課程號和相應的成績,然後再將其與Course表進行連接,的到最終結果。

嵌套查詢

在SQL語言中,一個SELECT-FROM-WHERE語句成爲一個查詢塊。將一個查詢塊嵌套在另一個查詢塊的WHERE子句或HAVING短語的條件中的查詢稱爲嵌套查詢(nested query)。例如:

Select Sname /*外層查詢或父查詢*/
From Student
where Sno in(
	Select Sno /*內層查詢或子查詢*/
	from SC
	where Cno=2);

本例中,下層查詢塊Select Sno from SC where Cno=‘2’是嵌套在上層查詢塊select Sname from Student where Sno in的where條件中的。上層的查詢塊稱爲外層查詢父查詢,下層查詢塊稱爲內層查詢子查詢
SQL允許多層嵌套查詢,但是子查詢的SELECT語句不能使用order by子句,order by子句只能對最終結果查詢。
嵌套查詢使用戶可以用多個簡單查詢構成複雜的查詢,從而增強SQL的查詢能力。以層層查詢的方式來構造程序正是SQL中“結構化”的含義所在

  1. 帶有in謂語的子查詢
    在嵌套查詢中,子查詢的結果往往是一個集合,所以謂語in是嵌套查詢中最經常使用的謂詞。

【3.55】查詢與“劉晨”在同一個系學習的學生。
先分步完成此查詢,在構成嵌套查詢
1⃣️ 確定“劉晨”所在系名

Select Sdept 
from Student
where Sname=‘劉晨’;

結果爲CS
2⃣️ 查找所有在CS系學習的學生。

Select Sno,Sname,Sdept
from Student
where Sdept=‘CS’;

將第一步查詢嵌入到第二步查詢的條件中,構造嵌套查詢如下:

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’);

然後執行該語句。本例也可以用自身連接來完成。

【3.56】查詢選修了課程名爲“信息系統”的學生學號和姓名
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=‘信息系統’;

【3.55】和【3.56】中子查詢的查詢條件不依賴於父查詢,這類子查詢稱爲不相關子查詢如果子查詢的查詢條件依賴於父查詢,這類子查詢稱爲相關子查詢(correlated subquery),整個查詢語句稱爲**相關嵌套查詢(correlated nested query)**語句。

  1. 帶有比較運算符的子查詢
    【3.57】找出每個學生超過他自己選修課程平均成績的課程號。
Select Sno,Cno
from SC x
where Grade>=(
	Select avg(Grade)
	from SC y
	where y.Sno=x.Sno
);

x是表SC的別名,又稱爲元組變量,可以用來表示SC的一個元組。內層查詢是求一個學生所有選修課程平均成績的,至於哪個學生的平均成績要看參數x.Sno的值,而該值是與父查詢相關的,因此這類查詢稱爲相關子查詢
這個語句的一種可能的執行過程採用一下三個步驟。
1
2
3
然後外層查詢取出下一個元組重複做上述1至3步驟的處理,直到外層的SC元組全部處理完畢。

求解相關子查詢不能像求解不相關子查詢那樣一次將子查詢求解出來,然後求解父查詢。 內層查詢由於與外層查詢有關,因此必須反覆求值。

  1. 帶有ANY(SOME)或ALL謂詞的子查詢

未完成待續

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