SQL之复杂查询与视图

Posted 计算机小白的爬坑之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL之复杂查询与视图相关的知识,希望对你有一定的参考价值。

一、利用SQL表达复杂查询

子查询使用条件及定义

  1. 某一元素是否是某一集合的成员
  2. 某一个集合是否包含另一个集合
  3. 测试集合是否为空
  4. 测试集合是否存在重复元组

定义:出现在Where子句中的Select语句被称为子查询,子查询返回了一个集合,可通过与这个集合的比较来确定另一个查询集合。

三种类型的子查询:(NOT)IN子查询;θ-Some/θ-All子查询;(NOT)EXISTS子查询

1、(NOT)IN子查询

基本语法:表达式 [not] in (子查询)

示例:列出张三、王三同学的所有信息
Select * From Student Where Sname in (“张三”“王三”);

上述示例相当于
Select * From Student Where Sname =“张三” or Sname =“王三”;

示例:列出选修了001号课程的学生的学号和姓名
Select S#, Sname From Student Where s# in ( Select S# From sC Where C# =‘001');

示例:求既学过001号课程,又学过002号课程的学生的学号
Select S# From sc Where C# =‘001’and S# in ( Select S# From sc Where C# =‘002’);

(1) 非相关子查询

带有子查询的Select语句区分为内层和外层

非相关子查询:内层查询独立进行,没有涉及任何外层查询相关信息的子查询。
上述例子均为非相关子查询。

(2) 相关子查询

相关子查询:内层查询需要依靠外层查询的某些参量作为限定条件才能进行的子查询。
外层向内层传递的参量需要使用外层的表名或表别名来限定。

示例:求学过001号课程的同学的姓名
Select Sname From Student Stud Where s# in ( Select S# From sc Where S# = Stud.S# and C# =‘001’);

注意:相关子查询只能由外层向内层传递参数,而不能反之;这也称为变量的作用域原则。

2、θ-Some与θ-AII子查询

基本语法:表达式θ-some (子查询);表达式θ-all(子查询)

语法中,0是比较运算符:<,>, >= ,<=,=,<>。

语义:将表达式的值与子查询的结果进行比较:

  1. 如果表达式的值至少与子查询结果的某一个值相比较满足0关系,则“表达式0 some(子查询)"的结果便为真;
  2. 如果表达式的值与子查询结果的所有值相比较都满足0关系,则“表达式0 all(子查询)的结果便为真;

示例:找出工资最低的教师姓名
Select Tname From Teacher Where Salary <= all ( Select Salary From Teacher );

示例:找出001号课成绩不是最高的所有学生的学号
Select S# From sc Where C# =“001" and Score < some ( Select Score From sC Where C# ="001”);

示例:找出所有课程都不及格的学生姓名(相关子查询)
Select Sname From Student Where 60 > all ( Select Score From sc Where S# = Student.S# );

等价表达式
表达式=some(子查询)——表达式in(子查询)
表达式<> all(子查询)——表达式not in(子查询)

3、(NOT) EXISTS子查询

基本语法:[not] Exists (子查询)
语义:子查询结果中有无元组存在

示例:检索学过001号教师主讲的所有课程的所有同学的姓名
Select Sname From Student Where not exists ( Select * From Course Where Course.T# =‘001'and not exists ( Select * From sc Where S# = Student.S# and C# = Course.C# ));
上述语句的意思:不存在有一门001号教师主讲的课程该同学没学过

示例:列出没学过李明老师讲授任何一门课程的所有同学的姓名
Select Sname From Student Where not exists ( Select * From Course, sC, Teacher Where Tname='李明’ and Course.T# =Teacher.T# and Course.C# = SC.c# and S# = Student.S# );

示例:列出至少学过98030101号同学学过所有课程的同学的学号
Select DISTINC S# From sc sc1 Where not exists (Select * From sc SC2 Where Sc2.S# =‘98030101' and not exists ( Select * From sc Where C# = SC2.C# and S# =SC1.S#));

示例:已知SPJ(Sno,Pno, Jno, Qty),其中Sno供应商号,Pno零件号,Jno工程号,Qty数量,列出至少用了供应商S1供应的全部零件的工程号
Select DISTINCT Jno From SPJ SPJ1 Where not exists (Select * From SPJ SPJ2 Where SPJ2.Sno ='S1' and not exists ( Select * From SPJ SPJ3 Where SPJ3.Pno = SPJ2.Pno and SPJ3.Jno = SPJ1.Jno ) );

二、利用SQL语言进行结果计算与聚集计算

1、结果计算

Select-From-Where语句中,Select子句后面不仅可是列名,而且可是一些计算表达式或聚集函数,表明在投影的同时直接进行一些运算
Select 列名 | expr | agfunc (列名) [[,列名|expr | agfunc (列名)].….]From 表名1[,表名2.….] [ Where 检索条件];

expr 可以是常量、列名、或由常量、列名、特殊函数及算术运算符构成的算术运算式。特殊函数的使用需结合各自DBMS的说明书
agfunc()是一些聚集函数

示例:求有差额(差额>0)的任意两位教师的薪水差额
Select T1.Tname as TR1,T2.Tname as TR2,T1.Salary -T2.Salary From Teacher T1,Teacher T2 Where T1.Salary > T2.Salary;

示例:依据学生年龄求学生的出生年份,当前是2015年
Select s.S#, s.Sname, 2015-s.Sage+1 as Syear From Student s;

2、聚集函数

SQL提供了五个作用在简单列值集合上的内置聚集函数agfunc,分别是:COUNT、SUM、AVG、MAX、MIN

示例:求计算机系教师的工资总额
Select Sum(Salary) From Teacher T, Dept Where Dept.Dname =‘计算机’ and Dept.D#=T.D#;

示例:求数据库课程的平均成绩
Select AVG(Score) From Course C, sCWhere C.Cname =‘数据库’ and C.C# =SC.C#;

三、利用SQL语言进行分组查询与分组过滤

分组:SQL可以将检索到的元组按照某一条件进行分类,具有相同条件值的元组划到一个组或一个集合中,同时处理多个组或集合的聚集运算。

1、分组查询

分组的基本语法Select 列名|expr | agfunc (列名) [[,列名 |expr | agfunc (列名)]….] From 表名1 [,表名2.….] [ Where 检索条件] [ Group by 分组条件];

分组条件可以是:列名1,列名2,…

示例:求每一个学生的平均成绩
Select S#, AVG(Score) From sc Group by S#;

示例:求每一门课程的平均成绩
Select C#, AVG(Score) From sc Group by C#;

聚集函数是不允许用于Where子句中的:Where子句是对每一元组进行条件过滤,而不是对集合进行条件过滤

2、分组过滤

若要对集合(即分组)进行条件过滤,即满足条件的集合/分组留下,不满足条件的集合/分组剔除。

Having子句,又称分组过滤子句。需要有Group by子句支持,换句话说,没有Group by子句,便不能有Having子句。
Select列名 |expr | agfunc(列名)[[列名 |expr | agfunc(列名)].….]From表名1[,表名2.….] [ Where 检索条件] [ Group by 分组条件 [ Having 分组过滤条件]];

示例:求不及格课程超过两门的同学的学号
Select S# From sc Where Score<60 Group by S# Having Count(*)>2;

示例:求有10人以上不及格的课程号
Select C# From sc Where Score < 60 Group by C# Having Count(*)>10;

示例:该同学那几门不及格课程的平均成绩
Select S#, Avg(Score) From sc Where S# in (Select S# From sc Where Score < 60 Group by S# Having Count(*)>2) Group by S# ;

四、利用SQL语言实现关系代数操作

1、并-交-差运算

SQL语言:并运算UNION,交运算INTERSECT,差运算EXCEPT。

基本语法形式
子查询 Union [ALL] [ Intersect [ALL] / Except [ALL] 子查询

通常情况下自动删除重复元组:不带ALL。若要保留重复的元组,则要带ALL。

假设子查询1的一个元组出现m次,子查询2的一个元组出现n次,则该元组在:
√子查询1 Union ALL 子查询2,出现m +n次
√子查询1 Intersect ALL 子查询2,出现min(m,n)次
√子查询1 Except ALL 子查询2,出现max(0, m - n)次

并运算示例:求学过002号课的同学或学过003号课的同学学号
Select S# From sC Where C# =‘002' UNION Select S# From sC Where C# ='003';

交运算示例:求既学过002号课,又学过003号课的同学学号
Select S# From sc Where C# = ‘002' INTERSECT Select S# From sC Where C# =‘003';

差运算示例:假定所有学生都有选课,求没学过002号课程的学生学号
等价于:所有学生减掉学过002号课的学生
Select DISTINCT S# From sc EXCEPT Select S# From sc Where C# =‘002';

2、空值的处理

空值检测:is [not ] null
测试指定列的值是否为空值
示例:找出年龄值为空的学生姓名
Select Sname From Student Where Sage is null ;
注意:上例条件不能写为Where Sage = null;空值是不能进行运算的

现行DBMS的空值处理小结

  1. 除is [not] null之外,空值不满足任何查找条件
  2. 如果null参与算术运算,则该算术表达式的值为null
  3. 如果null参与比较运算,则结果可视为false。在SQL-92中可看成unknown
  4. 如果null参与聚集运算,则除count(*)之外其它聚集函数都忽略null

3、内连接、外连接

SQL的高级语法中引入了内连接与外连接运算,具体形式:
Select 列名 [[,列名].….] From 表名1 [NATURAL] [INNER | LEFT | RIGHT |FULL [OUTER]] JOIN 表名2 ON 连接条件| Using (Colname , Colname ..) [Where 检索条件]...;


五、SQL语言之视图及其应用

1、SQL视图的概念和结构

对应概念模式的数据在SQL中被称为基本表(Table),
对应外模式的数据称为视图(View)。
视图不仅包含外模式,而且包含其E-C映像。

SQL的数据库结构

  1. 基本表是实际存储于存储文件中的表,基本表中的数据是需要存储的
  2. 视图在SQL中只存储其由基本表导出视图所需要的公式,即由基本表产生视图的映像信息,其数据并不存储,而是在运行过程中动态产生与维护的
  3. 对视图数据的更改最终要反映在对基本表的更改上。

2、SQL视图的定义

视图需要“先定义,再使用”定义视图
create view view_name[(列名[,列名].….)] as 子查询[with check option]

如果视图的属性名缺省,则默认为子查询结果中的属性名;也可以显式指明其所拥有的列名。
with check option指明当对视图进行insert , update , delete时,要检查进行insert/update/delete的元组是否满足视图定义中子查询中定义的条件表达式

示例:定义一个视图CompStud为计算机系的学生,通过该视图可以将Student表中其他系的学生屏蔽掉
Create View CompStud AS (Select * From Student Where D# in ( Select D# From Dept Where Dname =‘计算机’));

示例:定义一个视图Teach为教师任课的情况,把Teacher表中的个人隐私方面的信息,如工资等屏蔽掉,仅反映其教哪门课及其学分等。
Create View Teach AS ( Select T.Tname, c.Cname, Credit From Teacher T, Course c Where T.T#= C.T#);

3、SQL视图的使用

使用视图:定义好的视图,可以像Table一样,在SQL各种语句中使用

4、SQL视图的更新

SQL视图更新:是比较复杂的问题,因视图不保存数据,对视图的更新最终要反映到对基本表的更新上,而,视图定义的映射不是可逆的。

SQL视图更新的可执行性

  1. 如果视图的select目标列包含聚集函数,则不能更新
  2. 如果视图的select子句使用了unique或distinct,则不能更新
  3. 如果视图中包括了group by子句,则不能更新
  4. 如果视图中包括经算术表达式计算出来的列,则不能更新
  5. 如果视图是由单个表的列构成,但并没有包括主键,则不能更新
  6. 对于由单一Table子集构成的视图,即如果视图是从单个基本表使用选择、投影操作导出的,并且包含了基本表的主键,则可以更新

5、撤销视图

撤消视图Drop View view_name

以上是关于SQL之复杂查询与视图的主要内容,如果未能解决你的问题,请参考以下文章

SQL之复杂查询与视图

SQL入门经典之视图

SQL入门经典 之视图

SQL编程第三章 复杂一点的查询

sql语句联合查询 与 视图想比较的话,那个效率快,为啥。

MySQL之视图操作