資料庫 DQL 資料庫查詢語句
目錄
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頁 未完待續