数据查询功能查询功能是SQL按的核心功能,是数据库用的最多的操作,查询语句是SQL语句比较复杂的语句。以下查询用到的三张表如下所示:
Student表:
Sno | Sname | Ssex | Sage | Sdept |
---|---|---|---|---|
150752 | 孙兰昌 | 男 | 20 | 计算机系 |
150765 | 梁诗笛 | 女 | 19 | 计算机系 |
… | … | … | … | … |
Course表:
Cno | Cname | Credit | Semester |
---|---|---|---|
c01 | 高等数学 | 5 | 1 |
c02 | 数据结构 | 3 | 2 |
… | … | … | … |
SC表:
Sno | Cno | Grade |
---|---|---|
150752 | c01 | 90 |
150765 | c02 | 88 |
… | … | … |
查询语句的基本结构
查询语句的基本结构可描述为:
单表查询
distinct
去重
SQL语言中的distinct
关键字可以去掉查询结果的重复行,distinct
放在select
的后边、目标列名的前边。例如:select distinct Sno from SC
[not] in
、_%[]
匹配、escape
转义、order by
排序
- in确定集合
in
确定某个集合,not in
不在某个集合,例如:select Sname, Ssex from Student where Sdept in ('计算机系', '数学系')
此查询等价于select Sname, Ssex from Student where Sdept='计算机系' or Sdept='数学系'
select Sname, Ssex from Student where Sdept not in ('计算机系', '数学系')
此查询等价于select Sname, Ssex from Student where Sdept!='计算机系' and Sdept!='数学系'
- 字符串匹配
一般形式为:列名 [not] like <匹配串>
_
:匹配任意一个字符%
:匹配0个或多个字符[]
:匹配[]
中的任意一个字符。如[aeiou]
匹配a、e、i、o、u中的任何一个。对于连续的字母匹配,例如[abcd]
可以简写[a-d]
。[^]
:不匹配[]中的任何一个字符。如[^abc]
表示不匹配a、b、c。对于连续的字母可以简写例如[^a-d]
。
- escape转义字符匹配
语法格式:escape 转义字符
例如:where field like '%30\%%' escape '\'
- 对查询结果进行排序
排序语法格式:order by <列名> [asc | desc]
asc
:升序排序,desc
:降序排序。如果指定多个列排序,则按照列的先后顺序排序,即最前面的优先级最高。 - 使用聚合函数汇总数据
count([distinct] <列名>)
:统计本列非空列值个数。sum() ave() min() max()
功能类似
group by分组
语法:group by [分组依据列] [having <组约束条件>]
SQL先执行where
后执行group by
再执行having
,建议在所有分组之前进行的搜索条件放在where
中,分组之后的条件搜索放在having
中更为高效。
Note:
查询年龄小于20学生人数:select Sdept, count(*) from Student where age < 20 group by Sdept
,而不能写成:select Sdept, count(*) from Student group by Sdept having Sage < 20
,因为在分组之后只保留分组依据列以及聚合函数,因为执行到having
时已经没有Sage
列了。
多表连接查询
内连接
使用内连接时,如果两个表的相关字段满足连接条件,则从两个表提取数据并组合成新的记录。
语法格式:from table1 [inner] join table on <连接条件>
例如:select * from studnet inner join SC on Studnet.Sno = SC.Sno
自连接
在自连接时一定要有别名。
例如:查询与操作系统学分相同的课程的课程名和学分。select C1.Cname, C2.Credit from Course C1 join Course C2 on C1.Credit = C2.Credit where C2.Cname = '操作系统'
外连接
查找不满足条件的记录。left
以左表为基础对右表进行筛选,right
类似。
语法:from table1 left | right [outer] join table2 on <连接条件>
例如:查询学生的选课情况,包括选了课程的学生和没有选课程的学生,列出学号、姓名、课程号和成绩。select Studnet.Sno, Sname, Cno, Grade from Student left outer join SC on Student.Sno = SC.Sno
使用TOP限制结果集
语法:top n [percent] [with ties]
一般与order by
同时使用。
其中:
- n为非负整数
top n
表示取查询的前n行数据top n percent
:表示取查询结果的前n%行数据with ties
:包括并列的结果
例如:查询年龄最大的三个学生的信息,包括并列的情况。select top 3 with ties * from Student order by Sage desc
子查询
SQL语言中,一个select-from-where
语句称为一个查询块。一个查询块嵌入了另外一个select
、insert
、update
或delete
则称为子查询或内层查询。集合测试
语法:where 表达式 [not] in (子查询)
例如:
- 查询与小明同在一个系学习的学生。
select * from Student where Sdept in (select Sdept from Student where Sname='小明')
- 查询选了c02课程的学生。
select * from Student where Sno in (select Sno from SC where Cno='c02') and
,此查询也可以用多表连接查询实现:select * from Student as S join SC on S.Sno==SC.Sno where Sdept='计算机系' and Cno='c02'
比较测试
语法:where 表达式 比较运算符 (子查询)
其中比较运算符有:= <> < > <= >=
。
例如:
- 查询考试成绩高于平均成绩的学生:
select * from student from SC group by Sno having AVG(Grade) > (select AVG(Grade) from SC)
。集合测试和比较测试都是先执行子查询,在执行外层查询,子查询只执行一次且不依赖于外层查询,这样的查询称为不相关子查询或嵌套子查询。
存在测试
语法:where [not] exists (子查询)
- 存在测试先执行外层查询,后执行子查询;子层查询的次数由外层查询结果决定。
- 存在测试只返回真值或假值,所以在子查询中指定列名没有意义,通常用
select *
代替。
例如:查询选修了c01课程的学生:select * from Student where exists (select * from SC where Sno = Student.Sno and Cno = 'c01')