目录
三、数据查询(select)
(一)、查询语句格式
SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>] …
//目标列表达式可以是表中的属性列、表达式、字符串常量、函数
FROM <表名或视图名>[,<表名或视图名> ]…|(SELECT 语句)
[AS]<别名>
[ WHERE <条件表达式> ]
[ GROUP BY <列名1> [ HAVING <条件表达式> ] ]
[ ORDER BY <列名2> [ ASC|DESC ] ];
理解语句:整个select语句的含义是,根据where子句的条件表达式从from子句指定的基本表、视图、派生表中找出满足条件的元组,再按select子句中的目标列表达式选出元组中的属性值形成结果表。
SELECT子句:指定要显示的属性列
FROM子句:指定查询对象(基本表或视图)
WHERE子句:指定查询条件
GROUP BY子句:对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。
HAVING短语:只有满足指定条件的组才予以输出
ORDER BY子句:对查询结果表按指定列值的升序或降序排序
(二)、单表查询
1、查询范围:查询仅涉及一个表
2、选择表中的若干列
查询指定列:
[例3.16] 查询全体学生的学号与姓名。
SELECT Sno,Sname
FROM Student;
[例3.17] 查询全体学生的姓名、学号、所在系。
SELECT Sname,Sno,Sdept
FROM Student;
查询全部列:
选出所有属性列的两种方法:
- 在SELECT关键字后面列出所有列名
- 将<目标列表达式>指定为 *
[例3.18] 查询全体学生的详细记录
SELECT Sno,Sname,Ssex,Sage,Sdept
FROM Student;
或
SELECT *
FROM Student;
查询经过计算的值:
[例3.20]
SELECT Sname,'Year of Birth: ',2014-Sage,LOWER(Sdept)
FROM Student;
使用列别名改变查询结果的列标题:
SELECT Sname NAME,'Year of Birth:' BIRTH,
2014-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT
FROM Student;
3、选择表中的若干元组
消除取值重复的行:使用distinct消除重复
指定DISTINCT关键词,去掉表中重复的行
SELECT DISTINCT Sno
FROM SC;
查询满足条件的元组:使用where子句实现
[例3.23]查询所有年龄在20岁以下的学生姓名及其年龄。
SELECT Sname,Sage
FROM Student
WHERE Sage < 20;
WHERE Sage BETWEEN 20 AND 23;
WHERE Sdept IN ('CS','MA’,'IS' );
WHERE Sno LIKE ‘201215121';
WHERE Sname LIKE '刘%';
//百分号%代表任意长度的字符串
WHERE Sname LIKE '欧阳__';
//下横线代表任意单个字符
WHERE Grade IS NULL
WHERE Sdept= 'CS' AND Sage<20;
4、ORDER BY子句
作用:用户可以用ORDER BY子句对查询结果按照一个或多个属性列的升序ASC、降序DESC排列,默认为升序。
[例3.40]查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。
SELECT *
FROM Student
ORDER BY Sdept, Sage DESC;
5、聚集函数
作用:为了进一步方便用户,增强检索功能,提供了SQL聚集函数。
统计元组个数
COUNT(*)
统计一列中值的个数
COUNT([DISTINCT|ALL] <列名>)
计算一列值的总和(此列必须为数值型)
SUM([DISTINCT|ALL] <列名>)
计算一列值的平均值(此列必须为数值型)
AVG([DISTINCT|ALL] <列名>)
求一列中的最大值和最小值
MAX([DISTINCT|ALL] <列名>)
MIN([DISTINCT|ALL] <列名>)
例题:
[例3.41] 查询学生总人数。
SELECT COUNT(*)
FROM Student;
[例3.42] 查询选修了课程的学生人数。
SELECT COUNT(DISTINCT Sno)
FROM SC;
[例3.43] 计算1号课程的学生平均成绩。
SELECT AVG(Grade)
FROM SC
WHERE Cno= ' 1 '
5.GROUP BY子句
作用:GROUP BY子句将查询结果按某一列或多列的值分组,值相等的为一组;如:选课人数相同的学生为一组,就可以统计选课数相同的学生人数了。
[例3.46] 求各个课程号及相应的选课人数。
SELECT Cno,COUNT(Sno)
FROM SC
GROUP BY Cno;
查询结果为:
注意:WHERE子句中是不能用聚集函数作为条件表达式,只能使用HAVING子句。
错误: WHERE AVG(Grade)>=90 !!!
正确: HAVING AVG(Grade)>=90 !!!
HAVING短语与WHERE子句的区别:
- 作用对象不同
- WHERE子句作用于基表或视图,从中选择满足条件的元组
- HAVING短语作用于组,从中选择满足条件的组。
(三)、连接查询
连接查询是针对多个表进行的,是关系数据库中最主要的查询,包括等值连接查询、自然连接查询、非等值连接查询、自身连接查询、外连接查询、复合条件连接查询。
连接查询的where子句中用来连接两个表的条件称为连接条件或连接谓词,一般格式为:
WHERE [<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>
1、等值连接与非等值连接、自然连接
等值连接:比较运算符为 =
例如:
WHERE Student.Sno = SC.Sno;
WHERE [<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名2>.]<列名3>
自然连接:在等值连接中把重复的属性列去掉则为自然连接。
2、自身连接
自身连接:一个表与其自己进行连接,需要给表起别名以示区别
由于所有属性名都是同名属性,因此必须使用别名前缀
[例 3.52]查询每一门课的间接先修课(即先修课的先修课)
SELECT FIRST.Cno, SECOND.Cpno
// 为要查询的表Course起两个名字别名:FIRST、SECOND
FROM Course FIRST, Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
3、外连接
外连接与普通连接的区别:
普通连接操作只输出满足连接条件的元组
外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出
左外连接:列出左边关系中所有的元组
右外连接:列出右边关系中所有的元组
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUT JOIN SC ON
(Student.Sno=SC.Sno);
4、多表连接
多表连接:两个以上的表进行连接
[例3.54]查询每个学生的学号、姓名、选修的课程名及成绩
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, SC, Course /*多表连接*/
WHERE Student.Sno = SC.Sno AND SC.Cno = Course.Cno;
(四)、嵌套查询
嵌套查询概述:
一个SELECT-FROM-WHERE语句称为一个查询块
将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询
例如:
SELECT Sname /*外层查询/父查询*/
FROM Student
WHERE Sno IN
( SELECT Sno /*内层查询/子查询*/
FROM SC
WHERE Cno= ' 2 ');
子查询的限制:不能使用ORDER BY子句
1、带有IN谓词的子查询
[例 3.56]查询选修了课程名为“信息系统”的学生学号和姓名
SELECT Sno,Sname ③ 最后在Student关系中
FROM Student 取出Sno和Sname
WHERE Sno IN
(SELECT Sno ② 然后在SC关系中找出选
FROM SC 修了3号课程的学生学号
WHERE Cno IN
(SELECT Cno ① 首先在Course关系中找出
FROM Course “信息系统”的课程号,为3号
WHERE Cname= '信息系统'
) );
2、带有比较运算符的子查询
当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或< >)。
用 = 代替IN :
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept =
(SELECT Sdept
FROM Student
WHERE Sname= '刘晨');
3、带有ANY(SOME)或ALL谓词的子查询
使用ANY或ALL谓词时必须同时使用比较运算
语义为:
> ANY 大于子查询结果中的某个值
> ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
>= ANY 大于等于子查询结果中的某个值
>= ALL 大于等于子查询结果中的所有值
[例 3.58] 查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
SELECT Sname,Sage
FROM Student
WHERE Sage < ANY
(SELECT Sage
FROM Student
WHERE Sdept= ' CS ')
AND Sdept <> ‘CS ' ; /*父查询块中的条件 */
4、带有EXISTS谓词的子查询
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
若内层查询结果非空,则外层的WHERE子句返回真值
若内层查询结果为空,则外层的WHERE子句返回假值
(五)、集合查询
集合操作的种类:并操作UNION—或、交操作INTERSECT—与、差操作EXCEPT
[例 3.64] 查询计算机科学系的学生及年龄不大于19岁的学生。
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19;
UNION:将多个查询结果合并起来时,系统自动去掉重复元组
UNION ALL:将多个查询结果合并起来时,保留重复元组
(六)、基于派生表的查询
子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表(Derived Table)成为主查询的查询对象
[例3.57]找出每个学生超过他自己选修课程平均成绩的课程号
SELECT Sno, Cno
FROM SC, (SELECTSno, 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