I.導語
數據庫查詢是數據庫操作的核心,SQL提供select語句進行查詢,其一般的格式爲:
select [all | distinct] <目標列表達式> [,<目標列表達式>] ...
from <表名或試圖名> [,<表名或試圖名>] ...
[where <條件表達式>]
[group by<列名1> [having <條件表達式>]]
[order by<列名2> [ASC | DESC]];
數據表
Student
學號 Sno | 姓名 Sname | 性別 Ssex | 年齡 Sage | 所在系 Sdept |
---|---|---|---|---|
20021521 | 李勇 | 男 | 20 | CS |
20021522 | 劉晨 | 女 | 19 | CS |
20021523 | 王敏 | 女 | 18 | MA |
20021524 | 張力 | 男 | 19 | IS |
Course
課程號 Cno | 課程名 Cname | 先行課 Cpno | 學分 Sage |
---|---|---|---|
1 | 數據庫 | 5 | 4 |
2 | 數學 | 2 | |
3 | 信息系統 | 1 | 4 |
4 | 操作系統 | 6 | 3 |
5 | 數據結構 | 7 | 4 |
6 | 數據處理 | 2 | |
7 | PASCAL語言 | 6 | 4 |
CS
學號 Sno | 課程號 Cno | 成績 Grade |
---|---|---|
20021521 | 1 | 92 |
20021521 | 2 | 85 |
20021521 | 3 | 88 |
20021522 | 2 | 90 |
20021522 | 3 | 80 |
– 查詢全體學生的學號和姓名
select Sno, Sname
from Student;
– 查詢學生表的全部信息
– 方式一
select *
from Student;
– 方式二,這種方式可以改變結果列的順序,下面這個例子將Sno和Sname交互了位置
select Sname, Sno, Sage, Ssex, Sdept
from Student;
– 查詢經過計算的值
select Sname, 2017-Sage
from Student;
– 改變表頭爲 birthYear
select Sname, 2017-Sage birthYear
from Student;
– select 等價於 select all
select all Sno
from SC;
上面的結果中Sno有重複行,如何消除重複,使用distinct關鍵字
– 消除重複行
select distinct Sno
from SC;
II.查詢滿足條件的元組
查詢滿足條件的元組可以通過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';
上面這個查詢操作,RDBMS可能的一種操作是全表掃描,取出一個元組,檢查該元組的Sdept列的值是否爲CS,如果相等,則取出Sname形成新的元組輸出,否則跳過。假設這個表有上萬條數據,而Sdept=CS的人數較少,可以在Sdept上建立索引,系統會利用索引的來查找Sdept=CS的元組,避免全表掃描,加快查詢效率。
– 查詢20歲以下的學生姓名和年齡
select Sname, Sage
from Student
where Sage<20;
– 查詢考試成績有不合格的學生學號
select distinct Sno
from SC
where Grade < 60;
這裏採用distinct消除重複行,因爲一個學號可能有幾門課不及格,只需要列出一次就行。
(2)確定範圍
– 查詢年齡在 20到23歲(包含20/23)之間的學生的姓名、系別、年齡
select Sname, Sdept, Sage
from Student
where Sage between 20 and 23;
– 查詢年齡不在 20到23歲(包含20/23)之間的學生的姓名、系別、年齡
select Sname, Sdept, Sage
from Student
where Sage not between 20 and 23;
(3)確定集合
– 查詢計算機系(CS)、數學系(MA)和信息系(IS)的學生姓名和性別
select Sname, Ssex
from Student
where Sdept in ('CS', 'MA', 'IS');
– 查詢不在計算機系(CS)、數學系(MA)和信息系(IS)的學生姓名和性別
select Sname, Ssex
from Student
where Sdept not in ('CS', 'MA', 'IS');
(4)字符匹配
一般格式
[not] like ‘<匹配串>’ [escape ‘<換碼字符>’]
其含義是查找指定屬性列值與匹配串相匹配的元組,匹配串可以是完整的字符串,也可以是帶有通配符%和_。
%:代表任意長度(可以是0)的字符串。例如a%b表示以a開頭b結尾的任意長度字符串。如abc, abgggc,ab都滿足該匹配。
_:代表任意單個字符。例如a_b,表示以a開頭b結尾的長度爲3的任意 字符串。如:abc,afc等都滿足該匹配。
– 查詢序號爲 200215121 的學生的詳細情況
select *
from Student
where Sno like '200215121';
這個等價於
select *
from Student
where Sno = '200215121';
如果like後面的匹配串不含通配符,like可用=(等於)來代替, not like可以用 != 或者<>(不等於)來代替。
– 查詢所有姓劉的學生的學號、姓名、性別
select Sno, Sname, Ssex
from Student
where Sname like '劉%';
– 查詢姓歐陽且全名長度爲3的學生姓名,一個漢字佔兩個_
select Sname
from student
where Sname like '歐陽__';
– 查詢名字中第二字爲陽的學生的姓名
select Sname
from Student
where Sname like '__陽%';
– 查詢不姓劉的學生的姓名
select Sname
from Student
where Sname not like '劉%';
如果查詢的字符串包含通配符 %或者_,這時就要使用escape’<換碼字符>’短語,對通配符進行轉義。
– 查詢DB_design課程的課程號和學分
select Cno, Ccredit
from Course
where Cname like 'DB/_design'
escape '/';
escape ‘/’表示 “/”爲轉義字符,這樣緊跟在“/” 後面的下劃線不在具有統配符的含義,轉義爲普通的字符。
– 查詢課程名以DB_開頭且倒數第三個字符爲i的課程詳情
select *
from Course
where Cname like 'DB/_%i__' escape '/';
(5)涉及空值的查詢
– 查詢成績爲空的學號和課程號
select Sno, Cno
from sc
where Grade is null;
(6)多條件查詢
邏輯運算符and 和 or可以聯結多個查詢條件。and的優先級高於or,但是可以通過括號來該變優先級。
– 查詢計算機系年齡在20歲以下的學生姓名
select Sname
from Student
where Sdept = 'CS' and Sage < 20;
– 查詢計算機系(CS)、數學系(MA)和信息系(IS)的學生姓名和性別
select Sname, Ssex
from Student
where Sdept in ('CS', 'MA', 'IS');
– 上面這個可以改造爲 or 聯結條件
select Sname, Ssex
from Student
where Sdept='CS' or Sdept='MA' or Sdept='IS';
III.order by子句
用戶可以通過order by 子句對查詢結果按照一個或多個屬性列的升序(asc)或降序(desc)排列,缺省爲升序排序。
– 查詢選修了3號課程的學生的學號及其成績並按照成績的降序排列
select Sno, Grade
from SC
where Cno=3
order by Grade desc;
對於空值的,升序空值排在最後,降序排在最前面。
– 查詢所有學生的信息,按系的升序排列,同一個系的按照年齡降序排序
select *
from Student
order by Sdept, Sage desc;
IV.聚集函數(aggregate functions)
SQL提供了許多聚集函數,主要包括:
函數 | 含義 |
---|---|
count( [distinct | all]* ) | 統計元組個數 |
sum( [distinct | all] <列名>) | 計算一列的總和(此列必須是數值型) |
avg( [distinct | all] <列名>) | 計算一列的平均值(此列必須是數值型) |
max( [distinct | all] <列名>) | 求一列的最大值 |
min( [distinct | all] <列名>) | 求一列的做小值 |
– 查詢學生的總數
select count(*)
from Student;
– 查詢選修了課程的學生人數 ,消除重複學號
select count(distinct Sno)
from SC;
– 計算1號課程的平均成績
select avg(Grade)
from SC
where Cno=1;
– 查詢1號課程的最高分
select max(Grade)
from SC
where Cno='1';
– 查詢200215122學生的總學分
select sum(Ccredit)
from sc, course
where sc.Sno='200215122' and sc.Cno = course.Cno;
V.group by子句
group by 子句將查詢結果按照某一列或多列的值進行分組,值相同的爲一組。
– 求各個課程號和相應的選課人數
select Cno,count(Sno)
from SC
group by Cno;
– 查詢選修了3門課以上的學生學號
select Sno
from sc
group by Sno
having count(*)>3;
where子句和having短語的的區別在於作用對象不同。where做用的是基本表或者視圖,從中選擇符合條件的元組;而having短語作用的是組,從中選擇符合條件的組。