where t1 like '%30!%%' escape '!'
3.2.9 NULL 空值查询
语法: 列名 IS [NOT] NULL 空值是未确定的值或其值尚不知道。
操作:查询还没有考试的学生的学号和相应的课程号
SELECT Sno, Cno FROM SC WHERE Grade IS NULL
注意:空值不是一个确定的值,所以不可以用等于或不等于来比较或衡量
3.2.10 AND OR 多重条件查询
语法:当需要多个查询条件时,可以在WHERE子句中使用逻辑运算符AND和OR来组成多条件查询
操作:查询C002和C003课程中考试成绩在80~90的学生的学号、课程号和成绩
SELECT Sno, Cno, Grade FROM SC
WHERE Cno IN( 'C002', 'C003')
AND Grade BETWEEN 80 AND 90
注意:OR的优先级小于AND,要改变运算的顺序可以通过加括号的方式实现
SELECT Sno, Cno, Grade FROM SC
WHERE (Cno = 'C001' OR Cno = 'C002')
AND Grade BETWEEN 80 AND 90
3.2.11 ORDER BY 对查询结果排序
语法:ORDER BY <列名> [ASC | DESC ] [,<列名> … ]
说明:按<列名>进行升序(ASC)或降序(DESC)排序;当用多个列排序时,这些列在该子句中出现的顺序决定了对结果集进行排序的方式
操作:查询全体学生详细信息,结果按系名升序排列,同一个系的学生按出生日期降序排列
SELECT * FROM Student ORDER BY Dept ASC, Birthdate DESC
3.2.12 使用聚合函数
语法:
COUNT(*):统计表中元组的个数。
COUNT([DISTINCT] <列名>):统计列值个数
SUM(<列名>):计算列值的和值(必须是数值型列)。
AVG(<列名>):计算列值的平均值(必须是数值型列)。
MAX(<列名>):得到列值的最大值。
MIN(<列名>):得到列值的最小值。
除COUNT(*)外,其他函数在计算过程中均忽略NULL值。
操作1:统计选修了课程(SC)的学生人数。
SELECT COUNT(DISTINCT Sno) FROM SC
操作2:计算学号为“0811101”的学生的考试总成绩
SELECT SUM(Grade) FROM SC WHERE Sno = '0811101'
注意!:聚合函数不能出现在WHERE子句中。
操作:查询学分最高的课程名,如下写法是错误的!
SELECT Cname FROM Course WHERE Credit = MAX(Credit)应该改为:
declare @credit int select @credit=max(credit) from course select cname from course where credit=@credit
3.2.13 GROUP BY 分组
语法: [GROUP BY <分组条件>]
作用:细化聚合函数的作用对象
操作1:统计每门课程的选课人数,列出课程号和选课人数。对查询结果按Cno的值分组,所有具有相同Cno值的元组为一组,然后再对每一组使用COUNT计算,求出每组的学生人数。
SELECT Cno, COUNT(Sno) FROM SC GROUP BY Cno
操作2:统计每个学生的选课门数和平均成绩。
SELECT Sno as 学号, COUNT(*) as 选课门数, AVG(Grade) as 平均成绩 FROM SC GROUP BY Sno
注意: 1.GROUP BY子句中的分组依据列必须是表中存在的列名,不能使用AS子句指派的列别名。 2.带有GROUP BY 子句的SELECT语句的查询列表中只能出现分组依据列和统计函数,因为分组后每个组只返回一行结果。
操作3:带WHERE子句的分组。统计每个系的女生人数。
SELECT Dept, Count(*) 女生人数 FROM Student WHERE Sex = '女' GROUP BY Dept
操作4:按多个列分组。统计每个系的男生人数和女生人数,结果按系名的升序排序。
SELECT Dept, Sex, Count(*) 人数, FROM Student GROUP BY Dept, Sex ORDER BY Dept
3.2.14 HAVING 限制分组结果
语法:HAVING用于对分组自身进行限制,它有点象WHERE子句,但它用于组而不是对单个记录。
操作1: 查询选课门数超过3门的学生的学号和选课门数。
SELECT Sno, Count(*) 选课门数 FROM SC GROUP BY Sno HAVING COUNT(*) > 3
处理过程:先执行GROUP BY子句对SC表数据按Sno进行分组,然后再用统计函数COUNT分别对每一组进行统计,最后筛选出统计结果满足大于3的组。分组的优先级大于查询,having是分组内操作。
操作2:查询选课门数大于等于4门的学生的平均成绩和选课门数
SELECT Sno, AVG(Grade) 平均成绩, COUNT(*) 选课门数 FROM SC GROUP BY Sno HAVING COUNT(*) >= 4
3.2.15 小结
1.在分组操作之前应用的筛选条件,比在WHERE子句中指定更有效。
2.在HAVING子句中指定的筛选条件,应该是那些必须在执行分组操作之后应用的筛选条件。
3.将所有应该在分组之前进行的筛选条件放在WHERE子句中而不是HAVING子句中。
3.3 多表查询
多表连接查询分类三种:
1.内连接(INNER JOIN):
分为三种:等值连接、自连接、不等连接
2.外连接(OUTER JOIN):
分为三种:左外连接、右外连接、全外连接
3.交叉连接(CROSS JOIN) :
没有WHERE子句,它返回连接表中所有数据
行的笛卡尔积
3.3.1 内连接
语法:ANSI方式的连接格式
FROM 表1 [INNER] JOIN 表2 ON <连接条件>
[<表名1.>][<列名1>]<比较运算符>[<表名2.>][<列名2>]
内连接执行过程:
首先取表1中的第1个元组,然后从头开始扫描表2,逐一查找满足连接条件的元组,
找到后就将表1中的第1个元组与该元组拼接起来,形成结果表中的一个元组。
表2全部查找完毕后,再取表1中的第2个元组,然后再从头开始扫描表2, …
重复这个过程,直到表1中的全部元组都处理完毕为止。
操作1:查询学生的选课情况。学生信息在student表中,选课信息在sc表中。两张表都存放着学生的学学号sno。
SELECT * FROM Student INNER JOIN SC ON Student.Sno=SC.Sno操作2:去除重复列。如果不指定查询结果的列名(如操作1)则直接将两个表拼接在一起,学号列会重复。为了避免重复,需要制定列名。
SELECT Student.Sno, Sname, Sex, Sage, Dept, Cno, Grade FROM Student
JOIN SC ON Student.Sno = SC.Sno
SELECT Sname, Cno, Grade FROM Student S JOIN SC ON S.Sno = SC.Sno WHERE Dept = '计算机系'注意:当为表指定了别名时,在查询语句中的其他地方,所有用到