数据库复习—Transact-SQL语句的高级应用

6.1 多表连接
6.1.1 连接概述
  1. 连接可以根据各个表之间的逻辑关系来利用一个表中的数据选择另外的表中的行。
  2. 连接条件可在 FROM 或 WHERE 子句中指定。连接条件与WHERE和HAVING搜索条件组合,用于控制FROM子句引用的基表中所选定的行。
  3. SQL Server处理连接时,查询引擎从多种可能的方法中选择最高效的方法处理连接。尽管不同连接的物理执行采用多种不同的优化,但是逻辑序列都应用下列子句实现:
  • FROM 子句中的连接条件。
  • WHERE 子句中的连接条件和搜索条件。
  • HAVING 子句中的搜索条件。
6.1.2 内连接
  1. 内连接(INNER JOIN) 通过比较数据源表间共享列的值,从多个源表检索符合条件的行的操作。可以使用等号运算符的连接,也可以连接两个不相等的列中的值 。

例6.1
查询选修课程号为c05109的学生的学号、姓名和期末成绩。
select student.studentno.sname,final
from student inner join score
on student.studentno=score.studentno
where score.courseno=‘c05109’
(
use teaching
select student.studentno,sname,final
from student,score
where score.courseno=‘c05109’ and student.studentno=score.studentno
) 亦可

例6.2
查询选修课程号为c05103且平时成绩高于80分的学生的学号、姓名、平时成绩和期末成绩。
select student.studentno,sname,usually,final
from student inner join score
on student.studentno=score.studentno and usually>80
where score.courseno=‘c05103’

6.1.3 外连接
  1. 外部连接(outer join)包括满足搜索条件的连接表中的所有行,甚至包括在其他连接表中没有匹配行的一个表中的行。
    (1)左外连接(left outer join)。包括 JOIN子句中左侧表中的所有行。右表中的行与左表中的行不匹配时,将为来自右表的所有结果集列赋以 NULL 值。
    例6.3
    利用左外连接方式查询08级学生的学号、姓名、平时成绩和期末成绩。
    select student.studentno,sname,usually,final
    from student left join score
    on student.studentno=score.studentno
    where substring(student.studentno,1,2)=‘08’

    (2)右外连接(right outer join)
  • 外部连接的一种,其中包含 JOIN 子句中最右侧表的所有行。
  • 如果右侧表中的行与左侧表中的行不匹配,则将为结果集中来自左侧表的所有列分配 NULL 值。

例6.4
利用右外连接方式查询教师的排课情况。
select courseno,tname,teacher.teacherno,major
from teach_class right join teacher
on teach_class.teacherno=teacher.teacherno

(3)完全外连接

  • 若要通过在连接的结果中包括不匹配的行来保留不匹配信息,请使用完全外部连接。
  • SQL Server 提供了完全外部连接运算符 FULL OUTER JOIN,它将包括两个表中的所有行,不论另一个表中是否有匹配的值。
    例6.5
    利用完全外连接方式查询教师的排课情况。
    select courseno,tname,major,teacher.teacherno
    from teach_class full join teacher
    on teach_class.teacherno=teacher.teacherno
6.1.4 交叉连接(笛卡尔连接)

交叉连接(Cross Join )是在没有WHERE子句的情况下,产生的表的笛卡儿积。两个表作交叉连接时,结果集大小为二者行数之积。该种方式在实际过程中用的很少。
例6.6
显示student 表和score表的笛卡儿积。
select student.studentno,sname,score.*
from student cross join score

6.1.5 连接多个表
  • 使用SELECT语句进行连接的表数目没有上限。但在一条SELECT语句中连接的表多于10个,那么数据库就很可能达不到最优化设计,SQL Server 2005引擎的执行计划会变得非常繁琐 。
  • 需要注意:对于3个以上关系表的连接查询,一般遵循下列规则:连接n个表至少需要n-1个连接条件,以避免笛卡儿积的出现。为了缩小结果集,采用多于n-1个连接条件或使用其他条件都是允许的。
    例6.7
    查询08级学生的学号、姓名、课程名、期末成绩及学分。
    select student.studentno,sname,cname,final,credit
    from score join student on
    student.studentno=score.studentno
    join course on
    score.courseno=course.courseno
    where
    substring(student.studentno,1,2)=‘08’

    例6.8
    查询计算机学院的老师的教师号、姓名、上课班级号、课程名和学分。
    select teacher.teacherno,tname,class.classno,cname,credit
    from teach_class join teacher
    on teach_class.teacherno=teacher.teacherno
    join course on
    teach_class.courseno=course.courseno
    where teacher.department=‘计算机学院’
6.1.6 合并多个结果集
  1. UNION操作符可以将多个SELECT语句的返回结果组合到一个结果集中。该结果集包含联合查询中的所有查询的全部行。下面列出了使用 UNION 合并两个查询结果集的基本规则:
  • 所有查询中的列数和列的顺序必须相同。
  • 数据类型必须兼容。
  1. 语法格式如下:
    select_statement union
    [all] select_statement

例6.9
合并结果集示例。
create table t1 (a int,b nchar(4),c nchar(4))
insert into t1 values(1,‘aaa’,‘jkl’)
insert into t1 values(2,‘bbb’,‘mno’)
insert into t1 values(2,‘ccc’,‘pqr’)
create table t2 (a nchar(4),b float)
insert into t2 values(‘kkk’,1.000)
insert inot t2 values(‘mmm’,3.000)
select a,b from t1 union
select b,a from t2

6.2 使用子查询
6.2.1 子查询介绍
  1. 子查询就是一个嵌套在SELECT、INSERT、UPDATE或DELETE语句或其他子查询中的查询子查询可以把一个复杂的查询分解成一系列的逻辑步骤,利用单个语句的组合解决复杂的查询问题。
  2. 可以使用连接替代子查询,也可以使用子查询替代表达式。
  3. SQL Server 2005对嵌套查询的处理过程是从内层向外层处理,即先处理最内层的子查询,然后把查询的结果用于其外查询的查询条件,再层层向外求解,最后得出查询结果。
  4. 使用子查询时应该注意如下的事项:
  • 子查询需要用括号括起来。
  • 当需要返回一个值或一个值列表时,可以利用子查询代替一个表达式。也可以利用子查询返回含有多个列的结果集替代表或连接操作相同的功能。
  • 子查询不能够检索数据类型为varchar(max)、nvarchar(max) 和 varbinary(max)的列
  • 子查询中可以再包含子查询,嵌套层数可以达到16层。
6.2.2 利用子查询做表达式

在Transact-SQL语句中,可以把子查询的结果当成一个普通的表达式来看待,用在其外查询的选择条件中。此时子查询必须返回一个值或单个列值列表,此时的子查询可以替换WHERE子句中包含IN关键字的表达式。

例6.10
查询学号为的学生的入学成绩、所有学生的平均入学成绩及该学生成绩与所有学生的平均入学成绩的差。
select studentno,sname,point
,(select avg(point) from student) as ‘平均成绩’
,point -(select avg(point) from student) as ‘分数差值’
from student
where studentno=‘0828261367’

例6.11
获取期末成绩中含有高于93分的学生的学号、姓名、电话和Email。
select studentno,sname,phone,Email
from student
where studentno in (select studentno
from score where final>93)

例6.12
查询选修课程的多于2门、且期末成绩均在85分以上的学生的学号、姓名、电话和Email。
select studentno,sname,phone,Email
from student
where studentno in
(select studentno
from score where final>85
group by studentno having count(*)>2)

6.2.3 利用子查询关联数据
  1. 子查询可以作为动态表达式,该表达式可以随着外层查询的每一行的变化而变化。
  2. **创建关联子查询时,外部查询有多少行,子查询就执行多少次。 **

例6.13
查询期末成绩比该选修课程平均期末成绩低的学生的学号、课程号和期末成绩。
select studentno,couseno,final
from score as a
where final<(select avg(final)
from score as b
where a.courseno=b.courseno
group by courseno)

6.2.4 使用子查询生成派生表
  1. 利用子查询可以生成一个派生表,用于替代FROM子句中的数据源表,派生表可以定义一个别名,即子查询的结果集可以作为外层查询的源表。实际上是在FROM子句中使用子查询。

例6.14
查询期末成绩高于85分、总评成绩高于90分的学生的学号、课程号和总评成绩。
select tt.studentno,tt.courseno,tt.usually0.2+tt.final0.8 as ‘总评成绩’
from (select * from score where final>85) as tt
where tt.final0.8+tt.usually0.2>90

6.2.5 使用子查询修改表数据
  1. 利用子查询修改表数据就是利用一个嵌套在INSERT、UPDATE或DELETE语句的子查询成批的添加、更新和删除表中的数据。

  2. INSERT 语句中的 SELECT 子查询可用于将一个或多个其他的表或视图的值添加到表中。使用 SELECT 子查询可同时插入多行。
    例6.15
    创建一个表sc,将score表中学生的相关数据添加到sc表中,并要求计算总评成绩。
    create table sc
    (studentno nchar(10) not null,
    courseno nchar(6) not null,
    total numeric(6,2) not null)
    go
    insert into sc(studentno,courseno,total)
    select studentno,courseno,final0.8+usually0.2
    from score
    where substring(studentno,1,2)=‘08’
    go
    select * from sc

  3. UPDATE语句中的SELECT子查询可用于将一个或多个其他的表或视图的值进行更新。使用 SELECT子查询可同时更新多行数据。

  4. 在DELETE语句中利用子查询可以删除符合条件的数据行。实际上是通过将子查询的结果作为删除条件表达式中的一部分。
    例6.16
    将sc表中含有总分低于80课程的所有学生总分增加5%。
    update sc
    set total=total*1.05
    where courseno in
    (select courseno from sc
    where total<80)
    select * from sc

6.2.6 exists和not exists子句
  1. EXISTS 是SQL语句中的运算符号,在子查询中,如果存在一些匹配的行,结果为TURE。
  2. 在执行过程中,一旦查找到第1个匹配的行,查询就结束。
  3. NOT EXISTS 与 EXISTS 的工作方式类似。
    例6.17
    查询student表中是否存在1990年12月12日以后出生的学生,如果存在,输出学生的学号、姓名、生日和电话。
    select studentno,sname,birthday,phone
    from student
    where exists(
    select * from student
    where birthday<‘1990-12-12’)

附件:
使用到的数据库:
https://pan.baidu.com/s/1Lmbw_qSmC04wnPUUgwSKRA
提取码:djsz

猜你喜欢

转载自blog.csdn.net/qq_37590544/article/details/88119056
今日推荐