一、數(shù)據(jù)查詢語句的基本格式
二、單表查詢
查詢表中的若干列
查詢指定列
查詢經(jīng)過計算的值
選擇表中的若干元組
去重
條件查詢
order by 子句
聚集函數(shù)
group by 子句
三、連接查詢
等值與非等值連接查詢
外連接
多表連接
四、嵌套查詢
帶有in謂詞的子查詢
帶有比較運算符的子查詢
帶有any(some)或all謂詞的子查詢
帶有exists謂詞的子查詢
五、集合查詢
六、基于派生表的查詢
一、數(shù)據(jù)查詢語句的基本格式
? ? select 要查的內(nèi)容
? ? from 查找的對象
? ? where 查找的條件
? ? group by 按什么分組
? ? having 使用到函數(shù)的條件
? ? order by 按照什么條件排序
二、單表查詢
查詢表中的若干列
查詢指定列
? ? select 列名1,列名2[,列名3,...]
? ? from 表名;
? ? ? ? 如果要查詢表中的所有列并且不用列的顯示順序,那么可以用符號“*”來代替所有列名,如果想要改變顯示順序,那么就要將所有的表名按照你想要的順序?qū)懗鰜怼?/p>
? ? ? ? 如果想要顯示自己指定的列名可以在要查詢的列名的后面加一個空格,然后輸入自己想要的列名即可。
查詢經(jīng)過計算的值
? ? ? ? 如果想要查詢出經(jīng)過一定的處理的列值,那么只需要將列名換成表達式即可,表達式可以是算術表達式、函數(shù)和字符串常量等
例:查詢?nèi)w學生的姓名、出生年份和所在院系,要求給出生年份起別名:birthday,用小寫字母表示系名
? ? select Sname,2022-Sage birthday,lower(Sdept)
? ? from Student;
選擇表中的若干元組
去重
? ? ? ? 有時候我們查到的結(jié)果可能是重復的,如果我們想要消除這些行可以使用distinct來消除它們。
例:查詢選修了課程的學生學號,并去除重復的行。
? ? select distinct Sno
? ? from Sc;
條件查詢
? ? ? ? 條件查詢可以通過where子句實現(xiàn),下面是where子句的常用查詢條件。
查詢條件 謂詞
比較 =,>,<,>=,<=,!=,<>,!>,!<;NOT+上述比較運算符
確定范圍 between and,not between and
確定集合 in,not in
字符匹配 like,not like
空值 is null,is not null
多重條件(邏輯運算) and,or,not
(1)比較大小
例:查詢計算機科學系全體學生的名單
? ? select Sname
? ? from Student
? ? where Sdept = 'CS';
(2)確定范圍
例:查詢年齡在20~23歲(包括20歲和23歲)之間的學生的姓名、系別和年齡
? ? select Sname,Sdept,Sage
? ? from Student
? ? where Sage between 20 and 23;
(3)確定集合
例:查詢計算機科學系(CS)、數(shù)學系(MA)、信息系(IS)學生的姓名和性別。
? ? select Sname,Ssex
? ? from Student
? ? where Sdept in ('CS','MA','IS');
(4)字符匹配
? ? ? ? 在字符匹配中,%代表任意長度(可以為0)的字符串,下劃線代表任意單個字符。如果要查詢的字符串中含有%或者下劃線則可以用 escape 定義換碼字符。當匹配串中不含通配符時,可以用等于運算符代替like謂詞,用不等于運算符代替not like謂詞。
例:查詢以"DB_"開頭,且倒數(shù)第三個字符為i的課程的詳細情況。
? ? select *
? ? from Course
? ? where Cname like 'DB\_%i__' escape '\';
(5)涉及空值的查詢
? ? ? ? 空值查詢中的is和is not不能用等于或者不等于代替,等于或不等于的前提是有值,空值沒有值。
例:查詢所有有成績的學生學號和課程號。
? ? select Sno,Cno
? ? from Sc
? ? where Grade is not null
(6)多重條件查詢
? ? ? ? 邏輯運算符and和or可以用來連接多個查詢條件。and的優(yōu)先級高于or,但用戶也可以用括號改變優(yōu)先級。
例:查詢計算機科學系年齡在20歲以下的學生姓名。
? ? select Sname
? ? from Student
? ? where Sdept = 'CS' and Sage > 20;
order by 子句
? ? ? ? order by子句用來給查詢結(jié)果排序,ASC為升序排列,DESC為降序排列,默認值為升序??罩档娘@示次序有具體系統(tǒng)實現(xiàn)來決定。
例:查詢?nèi)w學生情況,查詢結(jié)果按所在系的系號升序排列,同一系中的學生按年齡降序排列。
? ? select *
? ? from Student
? ? order by Sdept ASC,Sage DESC
聚集函數(shù)
? ? ? ? 為了進一步方便用戶,增強檢索功能,下面是常用的一些聚合函數(shù)。
函數(shù)名 作用
count(*) 統(tǒng)計元組個數(shù)
count([distinct|all] <列名>) 統(tǒng)計一列中值的個數(shù)
sum([distinct|all] <列名>) 計算一列值的總和,列值必須是數(shù)值型
avg([distinct|all] <列名>) 計算一列值的平均值,列值必須是數(shù)值型
max([distinct|all] <列名>) 求一列值中的最大值
min([distinct|all] <列名>) 求一列值中的最小值
注:1.distinct代表計算時去除重復值,all代表計算時不去除重復值,默認為all。
? ? ? ? 2.當聚集函數(shù)遇到空值時,除count(*)外,都跳過空值而只處理非空值。
? ? ? ? 3.聚集函數(shù)只能用于select子句和group by中的having子句。
例:查詢選修了課程的學生人數(shù)
? ? select count(distinct Sno)
? ? from Sc;
group by 子句
? ? ? ? group by子句將查詢結(jié)果按某一列或多列的值分組,值相等的為一組。如果未對查詢結(jié)果分組,聚集函數(shù)將作用于整個查詢結(jié)果,分組后聚集函數(shù)將作用于每一組,即每一組都有一個函數(shù)值。
例:查詢選修了三門以上課程的學生學號。
? ? select Sno
? ? from Sc
? ? group by Sno
? ? having count(*) > 3;
三、連接查詢
? ? ? ? 通常情況下,只查詢一個表并不能滿足我們的需求,這時就引入了連接查詢。如果一個查詢同時涉及兩個以上的表,則稱之為連接查詢。
等值與非等值連接查詢
? ? ? ? 連接查詢的where子句中用來連接兩個表的條件稱為連接條件或連接謂詞,其一般格式為
? ? [<表名1>.]<列名1><比較運算符>[<表名2>.]<列名2>
? ? [<表名1>.]<列名1> between [<表名2>.]<列名2> and [<表名2>.]<列名3>
? ? ? ? 當比較運算符為“=”時,稱為等值連接,其余則為非等值連接。連接條件中的列名稱為連接字段,各連接字段的名稱不必相同,但必須是可比的。在等值連接中,去掉目標列中的重復列稱為自然連接
例:查詢選修2號課程且成績在90分以上的所有學生的學號和姓名。
? ? select Student.Sno,Sname
? ? from Student,Sc
? ? where Student.Sno = Sc.Sno and Sc.Cno = '2' and Sc.Grade > 90;
? ? 自身連接
? ? ? ? 一個表自己與自己連接叫做自身連接。
例:查詢每一門課的間接先修課(即先修課的先修課)。
? ? select first.Cno,second.Cpno
? ? from Course first,Course second
? ? where first.Cpno = second.Cno;
外連接
? ? ? ? 普通連接操作只輸出滿足連接條件的元組,外連接操作以指定表為主體,將主體表中不滿足連接條件的元組一并輸出。外連接分為左外連接和右外連接,如果列出左表中的所有元組,則稱為左外連接;列出右表的所有元組,則成為右外連接。
例:查詢每個學生及其選修課程的情況,未選課的學生的選課情況以空值輸出。
? ? select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
? ? from Student left outer join Sc on (Student.Sno = Sc.Sno);
? ? 或
? ? select Student.*,Sc.*
? ? from Student left outer join Sc using(Sno);
多表連接
? ? ? ? 兩個表以上的連接稱為多表連接
例:查詢每個學生的學號、姓名、選修的課程名及成績。
? ? 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短語的條件中的查詢稱為嵌套查詢。被嵌套的查詢塊稱為內(nèi)層查詢或子查詢,另一個則為外層查詢或父查詢。需要注意的是,group by子句只能對最終的查詢結(jié)果進行排序,也就是只能用在最外層的查詢中,不能用在任何子查詢中。
? ? ? ? 如果子查詢的條件不依賴于父查詢,則稱為不相關子查詢。如果子查詢的條件依賴于父查詢,則稱為相關子查詢。
帶有in謂詞的子查詢
例:查詢選修了課程名為“信息系統(tǒng)”的學生的學號和姓名。
? ? select Sno,Sname
? ? from Student
? ? where Sno in
? ? ? ? (select Sno
? ? ? ? from Sc
? ? ? ? where Cno in
? ? ? ? ? ? (select Cno
? ? ? ? ? ? from Course
? ? ? ? ? ? where Cname = '信息系統(tǒng)'
? ? ? ? ? ? )
? ? ? ? );
帶有比較運算符的子查詢
? ? ? ? 父查詢與子查詢之間用比較運算符進行連接,這時內(nèi)層查詢返回的是單個值。
例:找出每個學生超過他自己選修課程平均成績的課程號。
? ? select Sno,Cno
? ? from Sc x
? ? where Grade >= (
? ? ? ? select avg(Grade)
? ? ? ? from Sc y
? ? ? ? where x.Sno = y.Sno);
帶有any(some)或all謂詞的子查詢
? ? ? ? 子查詢返回多個值時要用any或all謂詞修飾符,并且必須同時使用比較運算符。謂詞any的意思是結(jié)果中的某個值,all的意思是結(jié)果中的所有值。
例:查詢非計算機科學系中比計算機科學系所有學生年齡都小的學生姓名及年齡。
? ? select Sname,Sage
? ? from Student
? ? where Sage < all
? ? ? ? (select Sage
? ? ? ? from Student
? ? ? ? where Sdept = 'CS')
? ? and Sdept <> 'CS';
帶有exists謂詞的子查詢
? ? ? ? 此類子查詢不返回任何數(shù)據(jù),只產(chǎn)生邏輯真值“true”或邏輯假值“false”。由exists引出的子查詢,其目標表達式通常用*,因為帶exists的子查詢只返回真值或假值,給出列名無實際意義。
例:查詢選修了全部課程的學生姓名。
? ? select Sname
? ? from Student
? ? where not exists
? ? ? ? (
? ? ? ? select *
? ? ? ? from Course
? ? ? ? where not exists
? ? ? ? ? ? (
? ? ? ? ? ? select *
? ? ? ? ? ? from Sc
? ? ? ? ? ? where Sno = Student.Sno and Cno = Course.Cno
? ? ? ? ? ? )
? ? ? ? );
五、集合查詢
? ? ? ? 查詢的結(jié)果是一個個元組的集合,所以多個查詢結(jié)果之間可以進行集合操作。集合操作主要包括交(intersect)、并(union)和差(except)。需要注意的是,參加集合操作的各查詢結(jié)果的列數(shù)和對應項的數(shù)據(jù)類型必須相同。
例:查詢計算機科學系的學生及年齡不大于19歲的學生。
? ? select *
? ? from Student
? ? where Sdept = 'CS'
? ? union
? ? select *
? ? from Student
? ? where Sage <= 19;
注意:并操作會自動去除相同的元組,如果不想去除重復的元組可以用union all操作符。
六、基于派生表的查詢
? ? ? ? 除去返回邏輯真假值的情況,子查詢返回的結(jié)果可以認為是一個表,那么子查詢的結(jié)果就可以作為一個臨時派生表出現(xiàn)在from子句中,成為主查詢的查詢對象。
例:找出每個學生超過他自己選修課程平均成績的課程號。
? ? select Sno,Cno
? ? from Sc,(select Sno,Avg(Grade) from Sc group by Sno)
? ? ? ? as Avg_sc(avg_sno,avg_grade)? ? -- 給派生表指定表名和屬性列名
? ? where Sc.Sno = Avg_sc.avg_sno and Sc.Grade >= Avg_sc.avg_grade;
注意:1.如果子查詢中沒有聚集函數(shù),那么可以不給派生表指定屬性列名。
? ? ? ? ? 2.通過from子句生成派生表時,as關鍵字可以省略,但必須為派生關系起一個別名。