目錄
自然連接(等值連接基礎上刪除重複行 其實就是將要顯示的字段都列出來)
DQL:數據查詢語言
操作對象:記錄(行)
關鍵字:select
符號約定:
<> 必須
[] 可選
{}或|:必須選其中之一
[,...N]:前面的項可以重複多次
select [all|distinct] <目標表達式> --distinct去掉重複行
from <表名或視圖名>
where <條件表達式>
group by <列名1> [having <條件表達式>]
order by <列名2> [asc|desc];
select 字段 [as] <別名> from 表名 where 條件表達式
1.簡單單表查詢
select Sno from SC; -- 查詢所有行的學號 等價於select all Sno from SC;
select distinct Sno from SC; -- 查詢所有行學號 去掉重複行 (相當於查詢共有多少種學號)
查詢結果取別名
select Sno as '學號' from SC; -- 查詢結果列名顯示爲‘學號’
--as可以省略 學號的引號sql server都允許省略 如下
select Sno 學號 from SC;
2.查詢條件
查詢條件 | 謂詞 |
---|---|
比較 | =,>,<,>=,<=,!=,<>,!>,!<;not 加上述比較運算符 |
確定範圍 | between and , not between and |
確定集合 | in , not in |
字符匹配 | like , not like |
空值 | is null , is not null |
多重條件(邏輯運算) | and , or , not |
!=與<>都是不等於
2.0全查詢與部分查詢
select * from 表名;
select * from Student; --查詢Student表的所有信息select 字段名1,字段名2... from 表名;
select Sname from Student; -- 查詢Student表的Sname信息 (只查詢Student表Sname這一列的所有信息)
2.1 比較
select Sname from Student where sdept='CS'; -- 查詢‘CS’部門所有學生的姓名
select Sname,Sage from Student where Sage<20; -- 查詢學生表所有年齡小於20的學生姓名與年齡
select distinct Sno from SC where Grade<60; -- 查詢不及格學生姓名 (可能某學生多門不及格 distinct去重)
2.2範圍 between / not between
select * from 表名 where 字段名x between A and B; -- 字段x值在[A,B]之內
select Sname from Student where Sage between 20 and 30; --查詢年齡在[20,30]的學生姓名
select Sname from Student where Sage not between 20 and 30; --查詢年齡不在[20,30]的學生姓名
2.3集合 in / not in
select * from Student where Sdept in ('CS','MA','IS'); -- 查詢'CS','MA','IS'三個部門的學生信息
(in其實是多個or的縮寫 上行語句等價於 select * from Student where Sdept='CS' or Sdept='MA' or Sdept='IS')
select * from Student where Sdept not in ('CS','MA','IS'); -- 查詢'CS','MA','IS'三個部門的學生信息
(同理上行語句等價於 select * from Student where Sdept!='CS' and Sdept!='MA' and Sdept!='IS'; )很明顯用in或not in比用or and強多了
2.4字符匹配like / not like
-- 模糊匹配
-- 格式:字段名 like "匹配規則";
-- 匹配規則2種:
匹配內容 %
"龍" 值爲"龍"
"%龍" 值以"龍"結尾
"龍%" 值以"龍"開頭
"%龍%" 值內包含"龍"
匹配個數 '__' 佔2個位置 (幾個下劃線佔幾個位置)注:sql server字符串只能用單引號擴起來
select * from Student where Sno like '201215121'; -- like後無%_ 而是寫了一個確定的值,like相當於=
select * from Student where Sname like '劉%'; -- 查詢所有姓劉的學生信息
select * from Student where Sname not like '劉%'; -- 查詢所有不姓劉的學生信息select * from Student where Sname like '歐陽_';--查詢姓歐陽且全名只有3個漢字的學生信息
select * from Student where Sname like '_陽%';--查詢名字中第二個字爲陽的學生信息
通配符%與_的轉義 escape '換碼字符'
select * from Course where Cname like 'DB\_Design' escape '\'; -- 查詢DB_Design課程的信息
(escape '換碼字符'換碼字符臨時定義 如這樣寫也行select * from Course where Cname like 'DB|_Design' escape '|';)select * from Course where Cname like 'DB\_%i__' escape '\';--查詢DB_開頭 倒數第三個字符爲i的課程信息
2.5空值查詢 is null / is not null
select Sno from SC where Grade is null;-- 查詢成績爲空值(曠考)的學生學號
select * from SC where Grade is not null;--查詢所有有成績的學生SC表信息
2.6多重條件查詢and / or
select * from Student where Sdept='CS' and Sage<20; -- 查詢計算機系年齡在20歲以下的學生信息
select * from Student where Sdept='CS' or Sdept='MA' or Sdept='IS' -- 查詢'CS','MA','IS'三個部門的學生信息
(in其實是多個or的縮寫 上行語句等價於 select * from Student where Sdept in ('CS','MA','IS');)
2.7order by子句
select * from SC where Cno=3 order by Grade desc; --查詢選修了3號課程的學生成績信息 按成績降序排列
select * from Student order by Sdept,Sage desc;--查詢全體學生信息,結果按系號升序排列,同一系的按年齡降序排列
(上行Sdept後省略了asc,因爲默認就是升序)
3.聚集(合)函數
count(*) | 統計元組(行)個數 |
count([distinct|all] <列名>) | 統計一列中值的個數 |
sum([distinct|all] <列名>) | 計算一列值的總和(此列必須是數值型) |
avg([distinct|all] <列名>) | 計算一列值的平均值(此列必須是數值型) |
max([distinct|all] <列名>) | 求一列值中的最大值 |
min([distinct|all] <列名>) | 求一列值中的最小值 |
3.1count
select count(*) from Student; -- 查詢學生總人數
select count(distinct Sno) from SC;--查詢選修了課程的學生人數
select count(Sno) from SC;--查詢選修了課程的學生人次
3.2avg
select avg(Grade) 平均成績 from SC where Cno='1';--計算1號課程學生平均成績
--計算1號課程學生平均成績 無成績(Grade爲null值)的人次不算 結果爲整數,無小數
3.3max
select max(Grade) from SC where Cno='1';--查詢選修了一號課程的學生的最高分數
3.4sum
select sum(Ccredit) from SC,Course where Sno='201215122' and SC.Cno=Course.Cno;--此處邏輯比較簡單選了就有學分
--查詢學生201215122選修課程的總學分 涉及多表查詢詳見後文 sum()對查詢的多行結果的Ccredit列求和
注意:聚集函數不能放在where後面,只能放在select子句後面或者group by的having子句後面(where是對單行一個一個篩選而聚集函數是對查詢後的結果進行的操作)
4.group by子句
group by子句將查詢結果按某一列或者多列的值分組,值相等的爲一組。
對查詢結果分組的目的是爲了細化聚集函數的作用對象。如果未對查詢結果分組,聚集函數將作用於整個查詢結果,如前例。分組後聚集函數將作用於每一個組,即每一組都有一個函數值
聚集函數合group by配合使用 就是在group by的基礎上對每組作用
4.1.select後接聚集函數
select cno 課程號 from SC;
select cno 課程號 from SC group by Cno;
select cno 課程號,count(Sno) 選課人數 from SC;--報錯
select cno 課程號,count(Sno) 選課人數 from SC group by Cno;--查詢各個課程的選課人數 結果如下 (改成Count(Cno)也一樣)
4.2.having子句接聚集函數
select Sno from SC;
select Sno from SC group by Sno;
select Sno,count(*) from SC group by Sno;
select Sno from SC group by Sno having Count(*)>1;--查詢選修了3門以上課程的學生學號 count是在group by的基礎上篩選的
4.3where勘誤
查詢平均成績大於等於80的學生學號和平均成績
select Sno,avg(Grade) from SC where avg(Grade)>=80 group by Sno; -- 錯誤 聚集函數不能放在where後面
select Sno,avg(Grade) from SC group by Sno having avg(Grade)>=80;--正確
5.連接查詢(多表查詢)
查詢同時涉及兩個以上的表,關係數據庫中最主要的查詢,包括等值連接查詢、自然連接查詢、非等值連接查詢、自身連接查詢、外連接查詢和複合條件連接查詢。
5.1等值連接與非等值連接查詢
連接查詢的where子句中用來連接兩個表的條件稱爲連接條件或連接謂詞
連接謂詞中的列名稱爲連接字段。連接條件中的各連接字段類型必須是可比的,但名字不必相同。連接運算符爲=時爲等值連接。使用其他運算符爲非等值連接
廣義笛卡爾積
多張表無條件的聯合查詢.沒有任何意義(就是全部組合)
select a.*,b.* from a,b;
需要在笛卡爾積基礎上加條件,纔有意義eg:select Student.*,SC.* from Student,SC;
等值連接
查詢每個學生及其選修課程的情況(課程表裏有選課和課程信息)
select Student.*,SC.* from Student,SC where Student.Sno=SC.Sno;-- sno相等的配對 等值連接
自然連接(等值連接基礎上刪除重複行 其實就是將要顯示的字段都列出來)
select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade from Student,SC where Student.Sno=SC.Sno;
--有歧義的加前綴. 無歧義的不用加
select Student.Sno,Sname from Student,SC where Student.Sno=SC.Sno and SC.Cno='2' and SC.Grade>90;
--查詢選修2號課程且成績在90分以上的所有學生的學號和姓名
5.2自身連接
一個表與其自己進行連接
select 別名1.字段,別名2.字段 from 表名 別名1,表名 別名2 where 別名1.字段 關係符 別名2.字段
select first.Cno,second.Cpno from Course first,Course second where first.Cpno=second.Cno;
-- 查詢每門課程的間接先修課 也即是先修課的先修課
5.3外連接
通常的連接操作中,只有滿足連接條件的元組才能作爲結果輸出,入上例中:Cno=2和6的由於Cpno=null導致沒有Cno與其相等,查詢結果中就沒有輸出了。外連接的主體表(左外連接就是左邊表 右外連接就是右邊表) 無保留全部輸出,副表匹配的顯示匹配信息,沒有匹配的顯示null
-- 學生選課情況 未選課的也列出來
select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade from Student left outer join SC on (Student.Sno=SC.Sno);(等價於此右外連接:
select Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade from SC right outer join Student on (Student.Sno=SC.Sno);)
5.4多表連接
-- 查詢每個學生選的每一門課及其成績 簡單where即可實現3表連接 普通連接無匹配的(未選課的)還是不顯示出來
select Student,Sno,Sname,Cname,Grade from Student,SC,Course where Student.Sno=SC.Sno and SC.cno=Course.Cno;
6.嵌套查詢(有些可用連接代替)
一個select-from-where語句稱爲一個查詢塊,將一個查詢塊嵌套在另一個查詢塊的where子句或having短語的條件中的查詢稱爲嵌套查詢
--查詢選修了2號課程的學生姓名
select Sname from Student where Sno in (select Sno from SC where Cno='2');
6.1 帶有in謂詞的子查詢
--查詢與劉晨在同一個系學習的學生
select * from Student where Sdept=(select Sdept from Student where Sname='劉晨');
(等價於下行的自身連接
select S1.* from Student s1,Student s2 where S1.Sdept=S2.Sdept and S2.Sname='劉晨';)
6.2 3張表的外連接
--查詢選修了課程名爲'信息系統'的學生學號和姓名
select Student.Sname,Student.Sno from Student where Sno in
(select Sno from SC where Cno in
(select Cno from Course where Cname='信息系統')
);
--where連接實現
select Student.Sname,Student.Sno from Student,SC,Course where Student.Sno=SC.Sno and SC.Cno=Course.Cno and Course.Cname='信息系統';
有些嵌套查詢可以用連接查詢運算代替(以上兩個都可以),有些不能用連接代替。目前商用數據庫管理系統對嵌套查詢的優化做得還不夠完善所以在實際應用中,能夠用連接運算表達的查詢儘可能採用連接運算。
子查詢的查詢條件不依賴於父查詢,這類子查詢稱爲不相關子查詢。子查詢的查詢條件依賴於父查詢,這類子查詢稱爲相關子查詢。
--到書本第105頁 未完待續