(数据库系统概论|王珊)第三章关系数据库标准语言SQL-第四节:数据查询
文章目錄
- ★★★★★SELECT語句格式★★★★★
- 一:單表查詢(查詢時只涉及一張表)
- (1)選擇表中的若干列
- A:查詢指定列
- B:查詢?nèi)苛?/li>
- C:查詢經(jīng)過計算的值
- ①:算數(shù)表達(dá)式
- ②:字符串常量及函數(shù)
- ③:使用列別名改變查詢結(jié)果標(biāo)題
- (2)選擇表中的若干行(元組)
- A:消除取值重復(fù)的行(DISTINCT)
- B:查詢滿足條件的元組
- ①:比較大小
- ②:確定范圍
- ③:確定集合
- ④:字符匹配
- ⑤:轉(zhuǎn)義字符
- ⑥:涉及空值的查詢
- ⑦:多重條件查詢
- (3)ORDER BY子句
- (4)聚集函數(shù)
- (5)GROUP BY子句
- 二:連接查詢(查詢時涉及多張表)
- (1)等值連接和非等值連接
- (2)自身連接
- (3)連接JOIN
- A:INNER JOIN(JOIN)
- B:LEFT JOIN(LEFT OUTER JOIN)
- C:RIGHT JOIN(RIGHT OUTER JOIN)
- D:FULL JOIN(FULL OUTER JOIN)
- (4)復(fù)合條件連接
- 三:嵌套查詢
- (1)帶有IN謂詞的子查詢
- (2)帶有比較運(yùn)算符的子查詢
- √:不相關(guān)子查詢和相關(guān)子查詢
- (3)帶有ANY(SOME)或ALL謂詞的子查詢
- (4)帶有EXISTS謂詞的子查詢
- 四:集合查詢
- 關(guān)于數(shù)據(jù)庫如何安裝,表如何建立這里不再介紹,請移步:(數(shù)據(jù)庫系統(tǒng)概論|王珊)第三章關(guān)系數(shù)據(jù)庫標(biāo)準(zhǔn)語言SQL-第零節(jié):MYSQL環(huán)境安裝和表的建立以及一些注意事項
- 所用表為(上面文章中也有完整代碼):
★★★★★SELECT語句格式★★★★★
數(shù)據(jù)庫最核心的操作便是數(shù)據(jù)查詢,SQL提供了SELECT語句實現(xiàn)該功能,其使用非常靈活而且有極其豐富的功能。格式如下
SELECT語句含義:根據(jù)WHERE子句的條件表達(dá)式從FROM子句指定的表、視圖中找出滿足條件的元組,再按照SELECT子句中的目標(biāo)列表達(dá)式選出元組中的屬性值形成結(jié)果表。如果有:
- GROUP BY:結(jié)果按<列名1>的值進(jìn)行分組,該屬性列值相等的元組為一個組;通常會在每組中作用聚集函數(shù);如果該子句還攜帶HAVING短語,則只有滿足指定條件的組才予以輸出
- ORDER BY:結(jié)果表還要按<列名2>的值的升序或降序排序
一:單表查詢(查詢時只涉及一張表)
(1)選擇表中的若干列
A:查詢指定列
演示:
【例1】查詢Student表中的學(xué)生及年齡
SELECT Sname,Sage from Student;B:查詢?nèi)苛?/h3>
語法:
- *作為通配符表示全部
演示:
【例2】查詢Student表中全部列
SELECT * from Student;C:查詢經(jīng)過計算的值
語法:SELECT子句的<目標(biāo)列表達(dá)式>不僅可以是屬性列,還可以是表達(dá)式,具體有
- 算數(shù)表達(dá)式
- 字符串常量
- 函數(shù)
- 列別名
①:算數(shù)表達(dá)式
演示:
【例3】根據(jù)年齡計算學(xué)生的出生日期
SELECT Sname,2022-Sage from Student;②:字符串常量及函數(shù)
演示:
【例4】使用小寫字母展示所在系別
SELECT Sname,LOWER(Sdept) from student;③:使用列別名改變查詢結(jié)果標(biāo)題
演示:
【例5】查詢Student表中的Sname和Sage,列標(biāo)題起別名為“姓名”和年齡
SELECT Sname `姓名`,Sage `年齡` from student;(2)選擇表中的若干行(元組)
A:消除取值重復(fù)的行(DISTINCT)
語法:前面說過投影操作可能會導(dǎo)致相同的行出現(xiàn)所以其結(jié)果必須消除重復(fù)行??梢允褂肈ISTINCT消除
演示:
【例6】:查詢SC表的Sno列,然后消除重復(fù)學(xué)號
SELECT DISTINCT Sno from SC;B:查詢滿足條件的元組
語法:通過WHERE子句實現(xiàn),常用的查詢條件如下
①:比較大小
演示:
【例7】在SC表中查詢成績大于85的同學(xué)的學(xué)號
SELECT Sno,Grade from SC WHERE Grade > 85;②:確定范圍
演示:
【例8】查血年齡在閉區(qū)間[19,20]的學(xué)生
SELECT Sname,Sage from student WHERE Sage BETWEEN 19 AND 20;
【例9】查血年齡不在閉區(qū)間[19,20]的學(xué)生
③:確定集合
演示:
【例10】查詢數(shù)字1是否在集合(1,2,3)中
- 由于滿足,所以會返回1
【例11】查詢數(shù)學(xué)系(MA)和計算機(jī)科學(xué)系(CS)學(xué)生的姓名
SELECT Sname,Sdept from student WHERE Sdept IN('MA','CS');【例12】查詢非數(shù)學(xué)系(MA)和非計算機(jī)科學(xué)系(CS)學(xué)生的姓名
SELECT Sname,Sdept from student WHERE Sdept NOT IN('MA','CS');④:字符匹配
注意:
- 可以使用=代替LIKE,使用!=代替NOT LIKE
- %可以代替多個字符
- _只能代替一個字符
演示:
【例13】查詢所有男生
SELECT Sname from student WHERE Ssex LIKE '男';
【例14】查詢所有姓劉的學(xué)生(%代替多個)
⑤:轉(zhuǎn)義字符
注意:
- ESCAPE '\' 表示將“ \” 翻譯為轉(zhuǎn)義字符
演示:
【例15】假設(shè)Course表中有一門課叫做DB_Design
- 如果不作處理,這里的_代替某個字符,產(chǎn)生歧義
⑥:涉及空值的查詢
演示:
【例16】查詢?nèi)鄙俪煽兊膶W(xué)生的學(xué)號和相應(yīng)的課程號
- 某些學(xué)生選修課程后沒有參加考試,所以有選課記錄,但沒有考試成績
⑦:多重條件查詢
注意:
- AND和 OR來聯(lián)結(jié)多個查詢條件
- AND的優(yōu)先級高于OR
- 可以用括號改變優(yōu)先級
演示:
【例17】 查詢計算機(jī)系年齡在20歲以下的學(xué)生姓名
SELECT * FROM student WHERE Sdept='CS' AND Sage < 20;(3)ORDER BY子句
語法:ORDER BY子句對查詢結(jié)果按照一個或多個屬性列進(jìn)行排序
- ASC-升序(默認(rèn))
- DESC-降序
演示:
【例18】查詢選修了3號課程的學(xué)生的學(xué)號及其成績,查詢結(jié)果按分?jǐn)?shù)降序排列
SELECT Sno,Grade from SC WHERE Cno='3' ORDER BY Grade DESC;【例19】查詢?nèi)w學(xué)生情況,查詢結(jié)果按所在系的系號升序排列,同一系中的學(xué)生按年齡降序排列
SELECT * FROM student ORDER BY Sdept,Sage DESC;(4)聚集函數(shù)
語法:主要有以下幾種
演示:
【例20】查詢學(xué)生的總?cè)藬?shù)
SELECT COUNT(Sno) FROM student;
【例21】查詢選修了課程的學(xué)生人數(shù)
【例22】 計算2號課程的學(xué)生平均成績
【例23】查詢選修2號課程的學(xué)生最高分?jǐn)?shù)
(5)GROUP BY子句
語法:GROUP BY子句將查詢結(jié)果按某一列或多列的值分組,值相等的分為一組
- 分組目的是為了細(xì)化聚集函數(shù)的作用對象:若未分組,聚集函數(shù)將會作用于整個查詢結(jié)果;若分組,聚集函數(shù)將會作用于每一個組,也即每一個組都有一個函數(shù)值
- 需要注意:WHERE子句作用于整個表或視圖,從中選擇出滿足條件的元組;HAVING短語作用于組,從中選擇滿足條件的組
相信讀完之后大家可能還是有點迷糊,舉個例子。比如我要查詢“各個課程對應(yīng)的選課人數(shù)”,如果沒有GROUP BY子句
SELECT Cno,Count(Sno) FROM sc;由于它會作用于整個查詢結(jié)果,所以直接統(tǒng)計出了記錄的條數(shù)
如果加入GROUP BY子句,按照課程號分組,那么GROUP BY會按照Cno進(jìn)行分組,相同的為一組,然后在每組內(nèi)統(tǒng)計Sno
而如果我只想顯示那些選課人數(shù)大于1以上的課程號呢,那么就可以使用HAVING短語,在組內(nèi)進(jìn)行篩選
SELECT Cno,Count(Sno) FROM sc GROUP BY Cno HAVING Count(Sno) > 1;
演示:
【例24】查詢平均成績大于等于80分的學(xué)生學(xué)號和平均成績
SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno HAVING AVG(Grade) >= 80;二:連接查詢(查詢時涉及多張表)
(1)等值連接和非等值連接
語法:在WHERE子句中寫入連接條件(又叫做連接每謂詞),其格式為
其中比較運(yùn)算符有:=、>、<、>=、<=、!=
- 當(dāng)運(yùn)算符為=時稱之為等值連接
- 當(dāng)運(yùn)算符不為=時稱之為非等值連接
演示:
【例25】查詢每個學(xué)生及其選修課程的情況
SELECT student.*,sc.* FROM student,sc WHERE student.Sno=sc.Sno;
【例26】使用自然連接(特殊的等值連接)完成【例25】
【例27】查詢選修2號課程且成績在80分以上的所有學(xué)生的學(xué)號和姓名
(2)自身連接
語法:所謂自身連接就是指一個表與自己連接
演示:
【例28】查詢每一門課的先修課的先修課
- 在Course表中有的只是每門課的直接先修課,要想得到先修課的先修課,那么就必須先找到一門課的先修課,然后再按此先修課的課程號查找它的先修課
因此,為Course表取兩個別名,分別為ONE和TWO
SELECT ONE.Cno,TWO.Cpno FROM Course ONE,Course TWO WHERE ONE.Cpno=TWO.Cno;當(dāng)然,還可以繼續(xù)找先修課的先修課的先修課
SELECT ONE.Cno,THREE.Cpno FROM Course ONE,Course TWO,course THREE WHERE ONE.Cpno=TWO.Cno AND TWO.Cpno=THREE.Cno;(3)連接JOIN
語法:SQL JOIN用于把來自兩個或多個表的行結(jié)合起來,其格式如下
SELECT column_name(s) FROM TABLE1//左表 <某某 JOIN>TABLE2//右表 ON TABLE1.column_name=TABLE2.column_name有如下幾類
- INNER JOIN(JOIN)
- LEFT JOIN(LEFT OUTER JOIN)
- RIGHT JOIN(RIGHT OUTER JOIN)
- FULL JOIN(FULL OUTER JOIN)
A:INNER JOIN(JOIN)
INNER JOIN(JOIN):關(guān)鍵字在表中存在至少一個匹配時返回行
演示:
【例29】以sc和course的Cno作為比對標(biāo)準(zhǔn),將相同連接在一起
SELECT Sno,sc.Cno,Grade,course.Cno,Cname,Cpno,Ccredit FROM sc INNER JOIN course ON(sc.Cno=course.Cno);B:LEFT JOIN(LEFT OUTER JOIN)
LEFT JOIN(LEFT OUTER JOIN):以左表為標(biāo)準(zhǔn),若右表中無匹配,則填NULL
SELECT Sno,sc.Cno,Grade,course.Cno,Cname,Cpno,Ccredit FROM sc LEFT JOIN course ON(sc.Cno=course.Cno);C:RIGHT JOIN(RIGHT OUTER JOIN)
RIGHT JOIN(RIGHT OUTER JOIN):以右表為標(biāo)準(zhǔn),若左表中無匹配,則填NULL
SELECT Sno,sc.Cno,Grade,course.Cno,Cname,Cpno,Ccredit FROM sc RIGHT JOIN course ON(sc.Cno=course.Cno);D:FULL JOIN(FULL OUTER JOIN)
FULL JOIN(FULL OUTER JOIN):本質(zhì)就是結(jié)合了LEFT JOIN和RIGHT JOIN
SELECT Sno,sc.Cno,Grade,course.Cno,Cname,Cpno,Ccredit FROM sc FULL JOIN course ON(sc.Cno=course.Cno);(4)復(fù)合條件連接
語法:沒有什么新的東西,就是涉及多張表,多個條件的查詢
演示:
【例30】查詢每個學(xué)生的學(xué)號、姓名、選修的課程名及成績
SELECT student.Sno,Sname,Cname,Grade FROM student,course,sc WHERE student.Sno=sc.Sno AND sc.Cno =course.Cno;三:嵌套查詢
在SQL中,一個SELECT-FROM-WHERE語句稱為一個查詢塊,將一個查詢塊嵌套在另一個查詢塊的WHERE子句或HAVING短語的條件中的查詢稱之為嵌套查詢。比如
在下面的這個例子中,內(nèi)層循環(huán)查出來的是符合Cno=2的Sno集合,外層循環(huán)則在該集合內(nèi)查詢是否有滿足的Sno,有的話顯示Sname即可
SELECT Sname //外層查詢 FROM Student WHERE Sno IN(SELECT Sno //內(nèi)層查詢FROM SCWHERE Cno='2')需要注意以下幾點
- 子查詢的SELECT語句不能使用ORDER BY子句
- 嵌套查詢往往可以轉(zhuǎn)換為對應(yīng)的連接運(yùn)算
(1)帶有IN謂詞的子查詢
語法:嵌套查詢中,子查詢的結(jié)果往往是一個集合,所以IN在嵌套查詢中使用次數(shù)最為頻繁
演示:
【例31】查詢與“劉晨”在同一個系學(xué)習(xí)的學(xué)生
- 考慮時可以由內(nèi)向外,先查詢出劉晨所在的系,然后在該集合中查詢滿足該集合的學(xué)生姓名
當(dāng)然嵌套查詢有時也可以轉(zhuǎn)化為連接完成
SELECT S1.Sno,S1.Sname,S1.Sdept FROM Student S1,Student S2 WHERE S1.Sdept=S2.Sdept AND S2.Sname='劉晨';【例32】查詢選修了課程名為“信息系統(tǒng)”的學(xué)生學(xué)號和姓名
- 首先在Course表中找出“信息系統(tǒng)”的Cno,形成Cno的集合
- 然后在SC表中找出哪些記錄的Cno在Cno集合內(nèi),形成Sno集合
- 最后在Student表中找出哪些記錄的Sno在Sno集合內(nèi),形成最終的結(jié)果
當(dāng)然本例也可以使用連接完成
(2)帶有比較運(yùn)算符的子查詢
語法:帶有比較運(yùn)算符的子查詢是指父查詢與子查詢之間用比較運(yùn)算符進(jìn)行連接。當(dāng)用戶能確切知道內(nèi)層查詢返回的是單個值時,可以使用>、<、=、>=、<=、!=等比較運(yùn)算符
演示:
【例33】查詢與“劉晨”在同一個系學(xué)習(xí)的學(xué)生
- 和【例31】一樣,只不過【例31】使用IN完成的
【例34】找出每個學(xué)生超過他選修課程平均成績的課程號
- 首先內(nèi)層循環(huán)要計算該學(xué)生的平均成績
- 外層循環(huán)使用>=
- 兩個循環(huán)要用Sno關(guān)聯(lián)在一起(相關(guān)子查詢)
√:不相關(guān)子查詢和相關(guān)子查詢
不相關(guān)子查詢:子查詢的查詢條件不依賴于父查詢
- 像【例31】、【例32】這樣的都是不相關(guān)子查詢
查詢時由里向外、逐層處理。每個子查詢在上一級查詢處理之前求解,子查詢的結(jié)果用于建立父查詢的查找條件
相關(guān)子查詢:子查詢的查詢條件依賴于父查詢
- 像【例34】這樣的都是相關(guān)子查詢
查詢時首先會取外層查詢中表的第一個元組,根據(jù)它與內(nèi)層查詢相關(guān)的屬性值處理內(nèi)層查詢,若WHERE子句返回為真,則將此元組放入結(jié)果表,然后再取外層表的下一個元組,接著重復(fù)上述過程
比如對于【例34】,其處理過程可能是下面這樣的
①:從外層查詢中取出sc的一個元祖x,將x.Sno的值(201215121)傳遞給內(nèi)層查詢
SELECT AVG(Grade) FROM sc y WHERE y.Sno='201215121';②:執(zhí)行內(nèi)層查詢,得到值88(近似),用該值代替內(nèi)層查詢,得到外層查詢
SELECT Sno,Cno FROM SC X WHERE Grade >= 88③:執(zhí)行這個查詢,得到
(201215121,1) (201215121,3)然后再取下一個元組重復(fù)上述過程即可
(3)帶有ANY(SOME)或ALL謂詞的子查詢
語法:內(nèi)層查詢返回單個值時使用比較運(yùn)算符。如果返回多個值要用ANY(有的是SOME)或ALL,然后同時使用比較運(yùn)算符
另外ANY或ALL與聚集函數(shù)、IN等謂詞有等價關(guān)系。也就是說在一些情況下,他們的寫法效果作用是一樣的
- 例如<ALL意思是小于所有值,那么它的等價含義就是小于最小值,也即<MIN
演示:
【例35】查詢其他系比計算機(jī)科學(xué)系任意一個學(xué)生年齡小的學(xué)生姓名和年齡
SELECT Sname,Sage FROM student WHERE Sage < ANY(SELECT Sage FROM student WHERE Sdept='CS') AND Sdept!='CS';
由于<ANY等價于<MAX,所以其等價寫法就是
(4)帶有EXISTS謂詞的子查詢
語法:EXISTS代表“存在量詞?{\exists}?”。帶有EXISTS謂詞的子查詢不返回任何數(shù)據(jù),只返回true或false。另外,由EXISTS引出的子查詢,其目標(biāo)列表達(dá)式通常都是*,因為給出列名沒有實際意義
- 若內(nèi)層查詢結(jié)果非空,則外層WHERE子句返回true
- 若內(nèi)層查詢結(jié)果為空,則外層WHERE子句返回false
與EXISTS相對的便是NOT EXISTS
- 若內(nèi)層查詢結(jié)果為空,則外層WHERE子句返回true
- 若內(nèi)層查詢結(jié)果非空,則外層WHERE子句返回false
需要注意的是,一些帶有EXISTS和NOT EXISTS謂詞的子查詢不能被其他形式的子查詢等價替換;但是所有帶IN謂詞,比較運(yùn)算符,ANY和ALL謂詞的子查詢都可以用帶EXISTS謂詞的子查詢替換
演示:
【例36】查詢所有選修了1號課程的學(xué)生姓名
- 處理時,首先會取外層查詢中Student表的第一個元組,根據(jù)它與內(nèi)層查詢相關(guān)的屬性值(Sno)處理內(nèi)層查詢,若WHERE子句返回為true則取外層查詢中該元組的Sname放入結(jié)果表
【例37】查詢與“劉晨”在同一個系學(xué)習(xí)的學(xué)生
- 和【例31】一樣,這里用EXISTS代替IN
【例38】查詢選修了全部課程的學(xué)生姓名
- 它等價于:查詢這樣一個學(xué)生,沒有一門課是它不選的
四:集合查詢
語法:SELECT語句的查詢結(jié)果是元組的集合,所以多個SELECT語句的結(jié)果可進(jìn)行集合操作。主要有:
- 并操作:UNION
- 交操作:INTERSECT
- 差操作:EXCEPT
需要注意的是查詢結(jié)果的列數(shù)必須相同且對應(yīng)項的數(shù)據(jù)類型也必須相同
演示:
【例39】查詢計算機(jī)科學(xué)系的學(xué)生及年齡不大于19歲的學(xué)生
SELECT Sname,Sage,Sdept FROM student WHERE Sdept='CS' UNION SELECT Sname,Sage,Sdept FROM student WHERE Sage<=19;【例40】查詢計算機(jī)科學(xué)系的學(xué)生與年齡不大于19歲的學(xué)生的交集
SELECT * FROM student WHERE Sdept='CS' INTERSECT SELECT * FROM student WHERE Sage <=19; 新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!總結(jié)
以上是生活随笔為你收集整理的(数据库系统概论|王珊)第三章关系数据库标准语言SQL-第四节:数据查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (数据库系统概论|王珊)第十一章并发控制
- 下一篇: machine learning (5)